Блокировка транзакции для выбранного запроса - PullRequest
22 голосов
/ 29 апреля 2011

Иногда у меня возникает следующая ошибка для хранимой процедуры, которая является только запросом выбора: Transaction (Process ID 91) was deadlocked on lock

Мое первоначальное понимание состояло в том, что запрос выбора не будет блокировать таблицу или не вызоветтупик, даже если таблица, к которой он пытается обратиться, обновляется / блокируется другим процессом, но кажется, что запрос на выборку также может вызвать взаимные блокировки.

Если я установил уровень изоляции для чтения незафиксированным для запроса, это решит проблему?

Ответы [ 3 ]

43 голосов
/ 29 апреля 2011

Мое первоначальное понимание состоит в том, что запрос Select не блокирует таблицу или не вызывает тупиковую ситуацию

Это понимание неверно.Запросы SELECT принимают общие блокировки в строках, которые они анализируют.Совместно используемые блокировки могут конфликтовать с исключительными блокировками из операторов update / delete / insert.Два оператора SELECT не собираются в тупик, но оператор SELECT может зайти в тупик с помощью ОБНОВЛЕНИЯ.При возникновении такой тупиковой ситуации SELECT обычно является жертвой, поскольку он не выполнял никаких обновлений, поэтому всегда проигрывает ничью.

Как и при любой тупиковой ситуации, вам необходимо опубликовать точную схему задействованных таблиц,точные операторы T-SQL и график тупиков.См. Как: сохранить графики взаимоблокировок (SQL Server Profiler) .С помощью этой информации вы можете получить инструкции, как исправить тупик.

6 голосов
/ 08 июля 2011

Как говорит Ремус, вы получаете тупики, потому что операции SELECT и UPDATE (или другие) блокируют друг друга, а не SELECT против SELECT. Вам нужно будет просмотреть все ваши запросы, касающиеся этой таблицы, и создать соответствующие индексы для этих запросов, и это решит ваши проблемы. Хорошее покрытие индексов является предпочтительным решением, а не использование табличных подсказок WITH (NOLOCK).

См. Следующую ссылку для хорошего руководства о том, как создавать индексы покрытия и как это влияет на взаимоблокировки.

4 голосов
/ 29 апреля 2011

Если вы используете SQL Server 2008, вы можете установить уровень изоляции для чтения незафиксированным, чтобы предотвратить взаимоблокировку. Смотрите эту ссылку . При чтении неподтвержденных или WITH (NOLOCK) необходимо помнить, что данные, перезапущенные запросом, могут быть НЕ РЕАЛЬНЫМИ!

...