Использование IsolationLevel.Snapshot, но БД все еще блокируется

Я являюсь частью команды, создающей веб-сайт на основе ADO.NET. Иногда у нас есть несколько разработчиков и инструмент автоматического тестирования, которые работают одновременно с копией базы данных для разработки.

Мы используем уровень изоляции моментальных снимков, который, насколько мне известно, использует оптимистичный параллелизм: вместо блокировки он надеется на лучшее и выдает исключение, если вы пытаетесь зафиксировать транзакцию, если затронутые строки были изменены другой стороной во время перевод.

Для использования уровня изоляции снимков мы используем:

<code>ALTER DATABASE <database name>
SET ALLOW_SNAPSHOT_ISOLATION ON;
</code>

и в C #:

<code>Transaction = SqlConnection.BeginTransaction(IsolationLevel.Snapshot);
</code>

Обратите внимание, что снимок IsolationLevel не совпадает с снимком ReadCommitted, который мы также пытались, но в настоящее время не используем.

Когда один из разработчиков входит в режим отладки и приостанавливает приложение .NET, он будет поддерживать соединение с активной транзакцией во время отладки. Теперь я ожидаю, что это не будет проблемой - в конце концов, все транзакции используют уровень изоляции моментального снимка, поэтому, пока одна транзакция приостановлена, другие транзакции должны иметь возможность нормально выполняться, поскольку приостановленная транзакция не удерживает никаких блокировок. Конечно, когда приостановленная транзакция завершается, она может обнаружить конфликт; но это приемлемо, если другие разработчики и автоматизированные тесты могут проходить беспрепятственно.

Однако на практике, когда один человек останавливает транзакцию во время отладки, все другие пользователи БД, пытающиеся получить доступ к одним и тем же строкам, блокируются, несмотря на использование уровня изоляции моментального снимка.

Кто-нибудь знает, почему это происходит, и / или как я могу достичь истинно оптимистичного (неблокирующего) параллелизма?

The resolution (an unfortunate one for me): Ремус Русану отметил, что писатели всегда блокируют других писателей; это подтверждаетсяMSDN - это не совсем так и звучит, но только упоминает, что нужно избегать замков читателя и писателя. Короче говоря, поведение, которое я хочу, не реализовано в SQL Server.

Ответы на вопрос(2)

когда один разработчик приостанавливает транзакцию? Кроме того, простое включение уровня изоляции снимка не имеет большого эффекта. Вы включили ALLOW_SNAPSHOT_ISOLATION?

Вот шаги:

ALTER DATABASE <databasename>
SET READ_COMMITTED_SNAPSHOT ON;
GO

ALTER DATABASE <database name>
SET ALLOW_SNAPSHOT_ISOLATION ON;
GO

После включения базы данных для изоляции моментальных снимков разработчики и пользователи должны запросить выполнение своих транзакций в этом режиме моментального снимка. Это должно быть сделано перед началом транзакции, либо с помощью клиентской директивы для объекта транзакции ADO.NET, либо внутри их запроса Transact-SQL с помощью следующего оператора:

SET TRANSACTION ISOLATION LEVEL SNAPSHOT

Радж

 Eamon Nerbonne25 июн. 2009 г., 16:37
База данных имеет разрешение allow_snapshot_isolation. Невыполнение этого требования приводит к немедленному исключению; Вы не можете установить уровень изоляции на моментальный снимок, когда allow_snapshot_isolation выключен (т.е. установка уровня изоляции не завершается сбоем в режиме без вывода сообщений). Я обновлю пост, чтобы отразить точные необходимые команды, спасибо!
Решение Вопроса

как и все уровни изоляции, влияет только на чтение. Пишет до сих пор блокируют друг друга. Если вы считаете, что то, что вы видите, представляют собой блоки чтения, вам следует продолжить изучение и проверить типы ресурсов и имена ресурсов, по которым происходит блокировка (wait_type и wait_resource вsys.dm_exec_requests).

Я бы не советовал вносить изменения в код, чтобы поддержать сценарий, который предполагает, что разработчики смотрят на отладчик в течение нескольких минут подряд. Если вы считаете, что этот сценарий может повториться в производстве (т. Е. Клиент зависает), то это уже другая история. Чтобы достичь желаемого, вы должны минимизировать число операций записи и выполнять все операции записи в конце транзакции за один вызов, который фиксируется перед возвратом. Таким образом, ни один клиент не может долго удерживать X-блокировки (не может зависать, удерживая X-блокировки). На практике это довольно сложно осуществить и требует от разработчиков большой дисциплины в том, как они пишут код доступа к данным.

 Eamon Nerbonne25 июн. 2009 г., 17:00
Такое поведение маловероятно в производстве. С другой стороны, версия для разработки очень важна, и я вполне хотел бы внести изменения в код, если это сгладит разработку. К сожалению, "svn-esque" стиль блокировки (надежда на лучшее и просто неудача в конфликте), похоже, не реализован. Возможность иметь длительные и сложные транзакции, не блокируя все небольшие транзакции, все равно будет полезна - так как мы используем меньше транзакций, которые идеально подходят только для того, чтобы избежать блокирования.
 25 июн. 2009 г., 17:22
Там нет серебряной пули. Но если вы обнаружите, что часто блокируетесь при записи и записи, вам следует подумать, почему это происходит, почему разные «запросы» вызвать обновления тех же данных. Возможно, вы сможете лучше разделить свое приложение, снизив вероятность дублирования. Возможно, некоторые обновления могут быть отложены, помещены в рабочую таблицу во время пользовательской транзакции (enque / dequeue может быть освобождена без блокировки, с осторожностью), а затем обработаны специальными пакетными процессами. Также убедитесь, что все транзакции блокируют только необходимый минимум (без блокировок страниц / таблиц, без эскалации, без тщательного сканирования таблиц).

Ваш ответ на вопрос