Sql-Server

普通 IX 鎖死鎖

  • March 16, 2022

我試圖弄清僵局。有問題的表mytb僅用於以下查詢:

delete mytb with (uplock,holdlock) where key_value=@value

通過 sp_executesql 呼叫。後面提到的兩個程序都使用相同的程式碼,除了鍵值。

我正在使用跟踪標誌 1222,這是伺服器日誌中的資源列表部分:

resource-list
objectlock lockPartition=0 objid=1433553235 subresource=FULL dbid=16 objectname=mydb.dbo.mytb id=lock5620a3480 mode=IX associatedObjectId=1433553235
owner-list
owner id=process4bd94c8 mode=IX
waiter-list
waiter id=process4c85288 mode=X requestType=convert
objectlock lockPartition=0 objid=1433553235 subresource=FULL dbid=16 objectname=mydb.dbo.mytb id=lock5620a3480 mode=IX associatedObjectId=1433553235
owner-list
owner id=process4c85288 mode=IX
waiter-list
waiter id=process4bd94c8 mode=X requestType=convert

我的理解如下:兩個程序(讓我們從它們的最後兩個 id 字元中稱它們為“c8”和“88”)設法在表上獲得相同的 IX 鎖,然後嘗試變成 X 鎖以刪除必要的行,但一個程序阻塞了另一個程序。

我的理解正確嗎?如果是,為什麼程序共享 IX 鎖?系統是否不應該拒絕訪問 IX 鎖來限制競爭條件的程序,這將導致第一個程序首先完成,然後第二個程序可以開始?

發表評論補充:在探勘更多時,我發現where條件上的索引不存在,而我希望它是聚集的主鍵。沒有這個索引會不會是死鎖的原因?

沒有這個索引會不會是死鎖的原因?

是的。每個查詢都將從一個 IX 鎖開始,然後開始獲取鍵範圍上的 U 鎖。由於holdlock提示,它將使用範圍鎖定,否則它將是單個鍵上的正常 U 鎖定。

在此處輸入圖像描述

但是在使用 (updlock,holdlock) 掃描數千行之後,每個都會嘗試將鎖升級到表級 X 鎖(對象鎖是分區的)

在此處輸入圖像描述

兩個會話都無法在表上獲得 X 鎖,因為另一個會話具有不兼容的 IX 鎖,因此死鎖。

使用選擇性索引,每個會話只需要讀取和鎖定少數鍵值,因此不會升級為表鎖定。

引用自:https://dba.stackexchange.com/questions/308740