Sql-Server

有時更新的行沒有被鎖定而不是更新觸發器

  • December 16, 2019

這是小型複製品:

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添加任何提示。

我的猜測是,存在這種瑣碎的計劃行為是為了避免死鎖情況。

引用自:https://dba.stackexchange.com/questions/255692