兩張表結構相同,差異在於索引類型:
tb1:唯一叢集索引 on atb2:唯一非叢集索引 on a兩個連線同步執行:
BEGIN TRAN;
UPDATE tb1 SET b = b + 1 WHERE a = 1; -- 連線 A
UPDATE tb1 SET b = b + 1 WHERE a = 1; -- 連線 B(阻塞)
連線 B 等待時,sp_lock 顯示連線 A 持有:
S 鎖IX 鎖U 鎖是「意圖更新」的非對稱鎖,專為 讀取階段尋找符合條件的行 而設計,防止死鎖。
WHERE 條件的行上申請 U 鎖(而非 S 鎖)| 已持有 \ 申請 | S | U | X |
|---|---|---|---|
| S | ✅ | ✅ | ❌ |
| U | ✅ | ❌ | ❌ |
| X | ❌ | ❌ | ❌ |
關鍵:U-U 不相容,兩條 UPDATE 同時尋找同一行時,第二條會在 U 鎖處等待,避免「雙方各持 S 鎖互相等待升級 X」的死鎖。
WHERE 條件有高選擇性索引,避免全表掃描產生大量 U 鎖READ_COMMITTED_SNAPSHOT(RCSI)將讀操作移至版本存儲,間接減少 U 鎖爭用sys.dm_tran_locks 中 resource_type=KEY 且 request_mode=U 的等待鏈U 鎖是 SQL Server 鎖管理器為「搜尋-更新」模式量身打造的防死鎖機制。理解其「先 U 後 X」的轉換邏輯與非對稱相容性,是診斷 UPDATE 阻塞與死鎖的關鑰鑰匙。