模擬 SQLSERVER 死鎖


環境: 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)與另一個進程被死鎖在 鎖 資源上,並且已被選作死鎖犧牲品。請重新運行該事務。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM