環境: sqlserver 2008
事務(進程 ID (n))與另一個進程被死鎖在鎖資源上,並且已被選作死鎖犧牲品。請重新運行
死鎖原理:
如兩個任務
任務1,已經鎖定R1,再進行請求R2<R2此時被任務2鎖定>
任務2,已經鎖定R2,再進行請求R1<R1此時被任務1鎖定>
導致兩個任務都進入了阻塞。SQLSERVER會選擇一個進行犧牲。
了解了原理后,來段SQL
-- 表結構和模擬數據 CREATE TABLE R1( ID INT NOT NULL, Name varchar(50) NULL, Num INT NULL CONSTRAINT [PK_R1] PRIMARY KEY CLUSTERED ( [ID] ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO INSERT INTO R1(ID, Name, Num) VALUES(1, '張三', 50) INSERT INTO R1(ID, Name, Num) VALUES(2, '李四', 50) CREATE TABLE R2( ID INT NOT NULL, Name varchar(50) NULL, Num INT NULL CONSTRAINT [PK_R2] PRIMARY KEY CLUSTERED ( [ID] ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO INSERT INTO R2(ID, Name, Num) VALUES(1, '張三', 50) INSERT INTO R2(ID, Name, Num) VALUES(2, '李四', 50)
任務1:
begin tran t1 -- R1 update R1 SET Num = 91 WHERE Name = '張三' -- R2 update R2 SET Num = 91 WHERE Name = '李四' rollback tran t1
任務2:
begin tran t2 -- R2 update R2 SET Num = 91 WHERE Name = '李四' -- R1 update R1 SET Num = 91 WHERE Name = '張三' rollback tran t2
執行方法:
1.在任務1里面執行前兩句(開啟事務, 鎖定R1)
2.然后切換到任務2里面執行前兩句(開啟事務, 鎖定R2)
3.在任務1里面執行鎖定R2(update R2…)此時要請求的R2被任務2鎖定
4.在任務2里面執行鎖定R1(Update R1…)此時請求的R1被任務1鎖定。
進入了死鎖,然后會彈出死鎖的信息。
消息 1205,級別 13,狀態 51,第 2 行
事務(進程 ID 89)與另一個進程被死鎖在 鎖 資源上,並且已被選作死鎖犧牲品。請重新運行該事務。