Voici une petite repro:
create table dbo.t (id int primary key, v int);
insert into dbo.t values (1, 1), (2, 2);
create table dbo.s (id int primary key, v int);
insert into dbo.s values (1, 10);
go
create trigger dbo.tr_t__iou
on dbo.t
instead of update
as
begin
set nocount on;
exec sp_lock @@spid;
end;
go
update dbo.t set v = 10 where id = 1;
update t
set
v = 10
from
dbo.s s join
dbo.t t on t.id = s.id;
update t
set
v = 10
from
(values (1, 10)) s(id, v) join
dbo.t t on t.id = s.id;
go
drop table dbo.t, dbo.s;
go
sp_lock
dans les trigger
rapports U -key lock
sur la ligne affectée dans le premier et le dernier cas, mais dans le second cas il n'y a pas du tout de lock
, comment l'expliquer?
Lorsque l'instruction de mise à jour se qualifie pour un plan trivial, la règle d'optimisation qui développe la partie déclencheur à la place de l'instruction (ExpandInsteadOfTriggerUpd
) inclut la partie du plan qui lit à partir de la table de base. Cette réécriture comprend l'ajout d'un indice UPDLOCK
à la lecture de base. Comme d'habitude, l'indicateur UPDLOCK
signifie que les verrous de mise à jour sont pris et maintenus jusqu'à la fin de la transaction.
Lorsque l'instruction ne remplit pas les conditions requises pour un plan trivial, la règle ExpandInsteadOfTriggerUpd
uniquement réécrit la partie écriture-curseur du plan, laissant la table de base lue intacte - pas de UPDLOCK
un indice est ajouté.
Je suppose que ce comportement de plan trivial existe pour éviter un scénario de blocage.