Sql-Server
有時更新的行沒有被鎖定而不是更新觸發器
這是小型複製品:
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
添加任何提示。我的猜測是,存在這種瑣碎的計劃行為是為了避免死鎖情況。