Автор: Craig Freedman Read Committed and Updates
Проведём эксперимент. Начнем с создания следующей простой схемы:
create table t1 (a int, b int)
create clustered index t1a on t1(a)
insert t1 values (1, 1)
insert t1 values (2, 2)
insert t1 values (3, 3)
create table t2 (a int)
insert t2 values (9)
В сеансе 1 заблокируем третью строку таблицы t1:
begin tran
update t1 set b = b where a = 3
Далее в сеансе 2 посмотрим spid сессии (он позже понадобится), и выполним представленное ниже изменение на уровне изоляции по умолчанию read committed:
select @@spid
update t1 set t1.b = t1.b
where exists (select * from t2 where t2.a = t1.b)
Для это изменения оптимизатор выберет следующий план запроса:
|–Clustered Index Update(OBJECT:([t1].[t1a]), SET:([t1].[b] = [t1].[b]))
……|–Top(ROWCOUNT est 0)
…………|–Nested Loops(Left Semi Join, WHERE:([t2].[a]=[t1].[b]))
………………|–Clustered Index Scan(OBJECT:([t1].[t1a]))
………………|–Table Scan(OBJECT:([t2]))
Чтобы узнать, нужно ли изменять строку, в этом плане выполняется просмотр таблицы t1 и каждой строки в таблице t2. Просмотр получает U блокировку на каждую строку t1. Если строка изменяется, уровень блокирования поднимается до X-блокировки. Если строка не изменяется, просмотр снимает со строки блокировку, поскольку у этой сессии используется режим изоляции read committed.