Ответ 1
Важным фактором здесь является то, что вы используете столбец в where
, который имеет некластеризованный индекс. Когда SQL Server обрабатывает обновление, он выглядит примерно так:
- Найти строки для обновления, используя блокировки U на затронутых данных
- Обновить строки, используя блокировки X для измененных данных
После завершения выполнения инструкции (по умолчанию READ COMMITTED
) блокировки U освобождаются, но блокировки X удерживаются до конца транзакции для поддержания изоляции.
В вашей некластеризованной индексной ситуации SQL Server ищет индекс по идентификатору и использует его для поиска фактической строки. Блокировка выглядит следующим образом:
- (сеанс 1, шаг 1) U-блокировка, взятая за значение индексного ключа для id = 1
- (сеанс 1, шаг 1) Х-блокировка, принятая для RID для строки с id = 1
- (Сессия 1, шаг 1) Блокировка U
- (Сессия 2) Блокировка U, взятая за значение индексного ключа для id = 1
- (сеанс 2) Блокировка X заблокирована для RID для строки с id = 1
- (сеанс 1, шаг 2) Блокировка U заблокирована по значению ключа ключа для id = 1 - DEADLOCK
Однако, когда индекс является кластеризованным индексом, не существует отдельного шага для преобразования ключа индекса в строку - значение кластерного индекса является идентификатором строки. Поэтому блокировка заканчивается следующим образом:
- (сеанс 1, шаг 1) U-блокировка, взятая за значение индексного ключа для id = 1
- (сеанс 1, шаг 1) Блокировка U обновлена до блокировки X
- (сеанс 2) Блокировка U заблокирована по значению ключа ключа для id = 1
- (сеанс 1, шаг 2) блокировка уже сохранена по значению ключа ключа для id = 1
- (сеанс 1, фиксация) заблокирован
- (Сессия 2) Предохранитель U
- (сеанс 2) U-блокировка обновлена до блокировки X
- (сеанс 2) заблокирован
Как всегда, имейте в виду, что, хотя это может быть план запроса, используемый в этом случае, оптимизатор может свободно выполнять разные вещи. Например, он может выбрать сканирование таблицы или вывести более крупнозернистые блокировки. В этих случаях взаимоблокировка может не произойти.