Sql-Server

從更新到意圖排他的PAGELOCK轉換死鎖

  • June 30, 2016

我們的一個客戶經常遇到死鎖。死鎖大多在同一個UPDATE語句上。死鎖遵循一種模式,其中兩個 SPID 都已獲取頁面上的更新 (U) 鎖,並且都嘗試將 U 頁面鎖上轉換為意向排他 (IX) 鎖。有時只涉及一頁;有時幾個。

我們使用跟踪標誌 1222擷取了死鎖跟踪。SQL Server 日誌顯示了許多具有以下模式的死鎖(按從下到上的順序):

waiter id=processe0dc2088 mode=U requestType=convert
waiter id=process2f9db2478 mode=U requestType=convert
waiter-list
owner id=processe0dc2088 mode=IX
owner id=process2f9db2478 mode=IX
owner-list
pagelock fileid=1 pageid=5794 dbid=2 objectname=tempdb.dbo.Item_Package_Site_Costs_Work id=lock1b22de480 mode=IX associatedObjectId=72057594131775488
resource-list

兩個程序都在執行相同的 UPDATE 語句來在這個 tempdb 表上設置一個標誌。此 tempdb 表包含需要在客戶端呼叫之間保持的資訊,直到客戶端完成。該表有一個相當長的索引,以表示唯一程序 ID 的 GUID 開頭。

我很難理解和模擬這種僵局。我已經用模擬數據嘗試了各種數量的記錄。

我的問題:

為什麼這些程序獲取 U 鎖,然後轉換為 IX? 我希望 DELETE 一開始就獲得 IX 鎖。

如何防止死鎖?

導致死鎖的語句如下。該過程剛剛對單個商店的商品列表進行了成本查找。它試圖指出發現了成本。

請注意,UPDATE 語句中有一個已棄用的 (NOLOCK)。這會是一個促成因素嗎?

UPDATE tempdb..Item_Package_Site_Costs_Work
SET ItemPkgSiteCost_VINCostFound = 1,
   ItemPkgSiteCost_VendCost_Key = SiteCosts_VendCost_Key
FROM tempdb..Item_Package_Site_Costs_Work (NOLOCK)
   INNER JOIN #SiteCosts
       ON ItemPkgSiteCost_GUID = @ProcGUID
       AND SiteCosts_Item_Type = 0 -- Standard
       AND ItemPkgSiteCost_Site_Key = SiteCosts_Input_Site_Key 
       AND ItemPkgSiteCost_Item_Key = SiteCosts_Item_Key
       AND ItemPkgSiteCost_ItemPkg_Key = SiteCosts_Input_Sel_ItemPkg_Key
       AND ItemPkgSiteCost_VendItem_Key = SiteCosts_VendItem_Key
       AND ISNULL(ItemPkgSiteCost_Qty_Recv, 1) = SiteCosts_Input_Qty_Recv

客戶的伺服器@@version是:

Microsoft SQL Server 2005 - 9.00.4035.00 (X64) 2008 年 11 月 24 日 16:17:31 版權所有 (c) 1988-2005 Windows NT 6.1(內部版本 7601:Service Pack 1)上的 Microsoft Corporation 標準版(64 位)

到目前為止,我無法擷取死鎖時使用的查詢計劃,並且我嘗試檢索查詢計劃的正常方法沒有返回任何內容(sys.dm_exec_query_plansys.dm_exec_text_query_plan都返回 NULL)。

更新 2013-08-29

客戶安裝了 SQL Server 2005 SP 4,但他們仍然看到此死鎖。我將繼續刪除正在修改的表上已棄用的 (NOLOCK),看看這是否修復了死鎖。

首先,程序持有 IX 並希望轉換為 U。這是預期的查詢中的提示。

兩個查詢都將在選擇期間獲取 IX 鎖,然後在需要發生更改(如果有)時轉換為 U。

這可以通過添加: WITH (XLOCK) 作為臨時表的提示來解決。

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