Transaction And Lock--唯一索引下INSERT導致的死鎖


背景:

曾經的一位同事問我:"數據庫只有並發INSERT 操作,會造成死鎖么?",我沒有太多思考地回答"不會",但真的不會嗎?

測試:

--=================================
--創建測試表
CREATE TABLE TB3
(
    ID INT PRIMARY KEY
)
GO
--===================================
--新開回話1
BEGIN TRAN 
INSERT INTO TB3
SELECT 2
WAITFOR DELAY '0:0:10'
INSERT INTO TB3
SELECT 1
--===================================
--新開回話2
BEGIN TRAN 
INSERT INTO TB3
SELECT 1

WAITFOR DELAY '0:0:10'
INSERT INTO TB3
SELECT 2

在上面的兩個回話中,由於主鍵(唯一約束)的限制,相同的key對應相同的lock Resource,導致需要等待對方所獲取的lock Resource,從而引發死鎖

而如果將主鍵修改為非唯一索引,則不會引發死鎖,相同的key對應不相同的lock Resource,因此不會造成相互等待也不引發死鎖。

--====================================================================

--華麗的PS

對於最常見的死鎖場景:

事務1 獲取表TB1上的資源,請求表TB2上的資源

事務2 獲取表TB2上的資源,請求表TB1上的資源

很多開發人員都會有意識保證各個事務訪問不同表的順序,從而避免此類死鎖的發生,但很少會考慮對相同表的訪問順序,尤其在輸入值被參數化的情況,如在下面的情況下:

BEGIN TRAN
UPDATE TB1
SET C2=@P2
WHERE C1=@P1

UPDATE TB1
SET C2=@P3
WHERE C1=@P3

COMMIT

 

在考慮是否會引發死鎖時,我們除了分析當前語句外,還得檢查這些語句所涉及到的表相關對象:觸發器+外鍵+索引,還需分析其他業務場景的潛在影響。

PS:很多我們自認為正確的小結論,洗洗(細細)分析下,根本就是錯誤,而這些西奧結論,可能造成很惡劣影響。

--========================================================

照例妹子鎮貼

圖片來源於一豆瓣友鄰


免責聲明!

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



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