#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. Помимо чтения грязных (незафиксированных) записей, выполнение незафиксированных операций чтения также может привести к пропуску записей или к повторному чтению! Вам лучше использовать изоляцию моментальных снимков (управление версиями строк).