1. 程式人生 > >SQL Server併發操作單個表時發生在page頁面級的死鎖

SQL Server併發操作單個表時發生在page頁面級的死鎖

最近遇到的死鎖問題都發生在併發操作單張表上,比較有意思,就模擬了重現了一下。
根據非聚集索引為條件,刪除某一個表的資料,類似於這麼一個語句,delete from table where nocluster_index in (x,y,z,m,n……)in裡面的內容不同,併發執行
某些情況下,可能會引發死鎖,如下簡單模擬重現一下這種情況。

如下用兩張表來模擬上述場景:TestPageLock代表要刪除的表,TestId來儲存用來刪除的Id

如下,用兩個Session即可,模擬併發,很快就會看到一條死鎖的資訊

擴充套件事件ring_buffer target中中的死鎖日誌

原理不難理解:
不同的Session要刪除的資料分佈在不同的資料頁面中,執行delete語句刪除資料的情況下,也是一個查詢然後加鎖的過程
當要刪除的資料落在不同的資料頁面上的時候,一旦加鎖順序發生衝突,就會產生死鎖
比如Session1刪除的資料分佈在50,80,120頁面上,Session2刪除的資料分佈在100,120,140頁面上,
Session1和Session2 要加鎖的目標存在交集,一旦存在交集,併發情況就可能存在加鎖順序衝突,類似死鎖因此而產生

解決:
最最簡單暴力的就是顯式鎖提示,這裡只能是tablockx;高階一點,遇到類似併發業務,可以使用佇列進行排隊。
估計會有人擔心tablockx的效能問題會不會鎖的太多了,測試發現直接顯式tablockx鎖提示,並不會非常大地影響效能,整體效能甚至會變高,
因為tablockx鎖模式更加簡單直接,會比行數需要的資源更少,因此在鎖定資源上,處理起來比較高效。