这是小型复制品:
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
在第一个和最后一个案例中受影响行的trigger
报告 U-key lock
中,但在第二个案例中根本没有lock
,如何解释?
当更新语句符合普通计划时,扩展语句 (
ExpandInsteadOfTriggerUpd
) 的而不是触发器部分的优化器规则包括从基表读取的计划部分。此重写包括向UPDLOCK
基本读取添加提示。像往常一样,UPDLOCK
提示意味着更新锁被获取并保持到事务结束。当语句不符合普通计划时,
ExpandInsteadOfTriggerUpd
规则只重写计划的写游标部分,保持基表读取不变 - 不UPDLOCK
添加任何提示。我的猜测是,存在这种琐碎的计划行为是为了避免死锁情况。