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

StackOverflow https://stackoverflow.com/questions/1044164

Вопрос

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

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

Чтобы использовать уровень изоляции моментальных снимков, мы используем:

ALTER DATABASE <database name>
SET ALLOW_SNAPSHOT_ISOLATION ON;

и в С#:

Transaction = SqlConnection.BeginTransaction(IsolationLevel.Snapshot);

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

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

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

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

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

Это было полезно?

Решение

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

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

Другие советы

Вы смотрели блокировки, когда один разработчик приостанавливает транзакцию?Кроме того, простое включение уровня изоляции моментальных снимков не дает большого эффекта.Вы включили 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

Радж

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top