天天看點

RDS SQL Server死鎖(Deadlock)系列之一使用DBCC捕獲死鎖問題引入DBCC捕獲死鎖死鎖測試死鎖分析解決方法最後總結

在日常運維阿裡雲rds sql server産品過程中,經常會被客戶問道:“應用程式被死鎖報錯啦?影響很大,到底是哪個程序導緻了死鎖發生的啊?怎麼解決啊?怎麼辦呀?”。從客戶一連串的問題中,我們深刻體會到了死鎖問題的緊迫性和影響之大。授人予魚而不如授人予漁,rds sql server死鎖系列文章就是為了幫助客人徹底解決死鎖問題為初衷而誕生的。本篇文章是系列文章的開篇,主要是讨論如何使用dbcc來捕獲死鎖資訊,内容包括:

dbcc捕獲死鎖

死鎖測試

死鎖分析

解決方法

dbcc捕獲死鎖是利用了sql server死鎖自動監測機制(預設每5秒運作一次)的傳回資訊,來将死鎖資訊記錄到資料庫日志記錄中,我們可以事後從錯誤日中來檢視這些有用的死鎖資訊,包括:

死鎖的犧牲程序

死鎖發生時的程序資訊

死鎖發生時争搶的資源

其實,dbcc捕獲死鎖資訊的方法本身非常簡單,隻需要使用dbcc指令打開兩個跟蹤标記(1222和1204)即可。方法如下:

跟蹤标記打開後,我們可以使用下面的語句再次檢查,確定标記打開成功:

截圖如下所示:

RDS SQL Server死鎖(Deadlock)系列之一使用DBCC捕獲死鎖問題引入DBCC捕獲死鎖死鎖測試死鎖分析解決方法最後總結

在這裡也順便把如何關閉死鎖跟蹤标記的方法寫到這裡:

擷取死鎖資訊的跟蹤标記已經打開,接下來進行死鎖測試。首先,在test資料庫下建立兩個測試表,表名分别為:dbo.test_deadlock1和dbo.test_deadlock2,代碼如下:

接下來,我們使用ssms打開一個新的連接配接,我們假設叫session 1,執行如下語句:

緊接着,我們使用ssms打開第二個連接配接,假設叫session 2,執行下面的語句:

一段時間以後,你會發現session 2執行的語句會被死鎖,做為了死鎖的犧牲品,錯誤資訊如下:

截圖為證:

RDS SQL Server死鎖(Deadlock)系列之一使用DBCC捕獲死鎖問題引入DBCC捕獲死鎖死鎖測試死鎖分析解決方法最後總結

死鎖場景,我們已經模拟出來了,接下來就是分析死鎖的時候了。讓我們檢視錯誤日志:

RDS SQL Server死鎖(Deadlock)系列之一使用DBCC捕獲死鎖問題引入DBCC捕獲死鎖死鎖測試死鎖分析解決方法最後總結

從這個死鎖資訊中,我們不難發現幾個非常有用的資訊:

參與死鎖的程序(process-list):鎖住其他程序的程序和死鎖犧牲者程序(會有deadlock victim标記)。

死鎖發生時,程序執行的語句(inputbuf):這個很重要,找到了語句就可以針對死鎖的語句進行針對性的優化解決。

程序争搶的資源(resource-list):死鎖發生時,到底程序之間在争搶什麼資源,死鎖的類型是什麼?本例資源争搶發生在表test.dbo.test_deadlock1 的主鍵上indexname=pk__test_dea__3213e83f07020f21,死鎖類型為x鎖(排他鎖)。

通過sql server錯誤日志中死鎖資訊的分析,我們可以從死鎖發生時程序執行的語句發現,死鎖發生的原因是兩個update程序操作的表順序不一緻導緻的。我們隻需要調整其中一個程序的update表順序即可解決這個死鎖問題。比如,調整session 2的執行語句,如下:

本篇分享講解了使用dbcc命名捕獲sql server死鎖資訊,是rds sql server死鎖系列文章的開篇,我們還會在後續系列文章分享更多的方法來捕獲死鎖資訊,敬請期待。