第十六章——處理鎖、阻塞和死鎖(3)——使用SQLServer Profiler偵測死鎖
前言:
作為DBA,可能經常會遇到有同事或者客戶反映經常發生死鎖,影響了系統的使用。此時,你需要儘快偵測和處理這類問題。
死鎖是當兩個或者以上的事務互相阻塞引起的。在這種情況下兩個事務會無限期地等待對方釋放資源以便操作。下面是死鎖的示意圖:
本文將使用SQLServer Profiler來跟蹤死鎖。
準備工作:
為了偵測死鎖,我們需要先模擬死鎖。本例將使用兩個不同的會話建立兩個事務。
步驟:
1、開啟SQLServer Profiler
2、選擇【新建跟蹤】,連到例項。
3、然後選擇【空白】模版:
4、在【事件選擇】頁中,展開Locks事件,並選擇以下事件:
1、Deadlock graph
2、Lock:Deadlock
3、Lock:Deadlock Chain
5、然後開啟TSQL事件,並選擇以下事件:
1、SQL:StmtCompleted
2、SQL:StmtStarting
6、點選【列篩選器】,在跟蹤屬性中,選擇資料庫名為需要偵測的資料庫,這裡使用AdventureWorks。
7、在【組織列】中,調整順序,如下:
8、點選執行。
9、然後開啟SQLServer,並開啟兩個連線。
10、 在第一個視窗中輸入並執行下面指令碼:
[sql] view plaincopyprint?
USEAdventureWorks
GO
SETTRANSACTIONISOLATIONLEVELREPEATABLEREAD
GO
BEGINTRANSACTION
SELECT*
FROMSales.SalesOrderDetail
WHERESalesOrderDetailID=121316
11、 然後在第二個視窗中輸入並執行下面指令碼:
[sql] view plaincopyprint?
USEAdventureWorks
GO
SETTRANSACTIONISOLATIONLEVELREPEATABLEREAD
BEGINTRANSACTION
SELECT*
FROMSales.SalesOrderDetail
WHERESalesOrderDetailID=121317
12、現在回到第一個窗體,並執行下面的指令碼:
[sql] view plaincopyprint
UPDATESales.SalesOrderDetail
SETOrderQty=2
WHERESalesOrderDetailID=121317
13、在第二個視窗輸入下面語句:
[sql] view plaincopyprint?
UPDATESales.SalesOrderDetail
SETOrderQty=2
WHERESalesOrderDetailID=121316
14、 然後在第二個視窗就會看到下面的訊息:
15、切換到SQLServer Profiler,可以看到下面的截圖:
16、 點選【Deadlock graph】時間,會顯示死鎖的影象:
17、可以儲存死鎖影象,右鍵然後選擇匯出事件資料,並另存為xdl檔案:
下面是其XML格式:
分析:
在本文中,首先建立一個Profiler空白模版,然後選擇下面的事件進行監控:
1、Deadlock graph
2、Lock:Deadlock
3、Lock:Deadlock Chain
4、SQL:StmtCompleted
5、SQL:StmtStarting
然後通過限定資料庫,來限制監控過得物件範圍。
在配置好之後,執行跟蹤,並在ssms中執行指令碼。SQLServer會自動處理和偵測這種型別的死鎖。然後會在第二個窗體中收到1205的錯誤。
在SQLServer Profiler中,演示瞭如何收集死鎖事件,在跟蹤結果中可以看到兩個事務嘗試在一個擁有共享鎖的鍵上新增排它鎖。通過死鎖影象,可以看到死鎖發生的細節。
為了避免或者最小化死鎖的發生,有一些建議可以參考:
1、確保你的事務儘可能地小,這裡指範圍。
2、使用較低隔離級別的事務。
3、對於可能的查詢,使用NOLOCK查詢提示。
4、規範化資料庫設計。
5、在需要的列上建立索引,以便是表不需要經常掃描,減少鎖問題的發生。
6、控制資料庫物件訪問的順序是相同的順序。
轉載於:https://blog.51cto.com/rmlifejun/1678092