从更新到意图独占的PAGELOCK转换死锁

Pau*_*ams 5 sql-server-2005 sql-server deadlock

我们的一位客户经常遇到僵局。死锁大多在同一个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
Run Code Online (Sandbox Code Playgroud)

两个进程都运行相同的 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
Run Code Online (Sandbox Code Playgroud)

客户的服务器@@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),看看这是否可以解决死锁。

Tho*_*ser 5

首先,进程持有 IX 并希望转换为 U。这是查询中的提示所预期的。

两个查询都将在选择期间使用 IX 锁,然后在需要发生更改(如果有)时转换为 U。

这可以通过添加: WITH (XLOCK) 作为临时表的提示来解决。


归档时间:

查看次数:

6130 次

最近记录:

9 年,10 月 前