Взаимоблокировка транзакций для запроса select

#sql #tsql #concurrency #deadlock

#sql #tsql #параллелизм #взаимоблокировка

Вопрос:

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

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

Если я установлю уровень изоляции для запроса read uncommitted, решит ли это проблему?

Ответ №1:

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

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

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

Комментарии:

1. @Remus Rusanu На самом деле, два оператора select могут привести к взаимоблокировке. Смотрите dba.stackexchange.com/questions/152768 /… . Можете ли вы это объяснить?

2. @RemusRusanu, вот вопрос о взаимоблокировке между двумя операторами Select: dba.stackexchange.com/questions/106354 /…

Ответ №2:

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

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

Комментарии:

1. Ссылка в настоящее время недоступна. Но я основал эту заметку / статью: sqlundercover.com/2019/03/05 /… . Я надеюсь, это кому-нибудь поможет.

Ответ №3:

Если вы используете SQL Server 2008, вы можете установить уровень изоляции на чтение uncommitted, чтобы предотвратить взаимоблокировку. Смотрите эту ссылку. При чтении без фиксации или С (NOLOCK) следует знать, что данные, повторно обработанные запросом, могут быть НЕНАСТОЯЩИМИ!

Комментарии:

1. Помимо чтения грязных (незафиксированных) записей, выполнение незафиксированных операций чтения также может привести к пропуску записей или к повторному чтению! Вам лучше использовать изоляцию моментальных снимков (управление версиями строк).