来自不同进程的相同临时表上的锁的死锁


17

我发现一个死锁似乎显示出我认为不可能的事情。死锁涉及两个过程:

1. process8cf948 SPID 63

  • 在临时表#PB_Cost_Excp_Process_Invoices_Work上执行ALTER TABLE。

  • 拥有对象ID 455743580的表#PB_Cost_Excp_Process_Invoices_Work上的IX锁

2. process4cb3708 SPID 72

  • 在UPDATE上对临时表#PB_Cost_Excp_Process_Invoices_Work进行执行,该表应该是它自己的表的唯一副本。

  • 在#PB_Cost_Excp_Process_Invoices_Work上拥有具有相同对象ID 455743580的 Sch-M锁!

这应该是不可能的。我想念什么吗?#Temporary表是否真的在这两个SPID之间重用?

这是在具有累积更新1(版本10.50.4260)的SQL Server 2008 R2 Service Pack 2上。

完整的未更改死锁跟踪如下。请注意,两个进程如何在具有相同表名#PB_Cost_Excp_Process_Invoices_Work_SNIP_0000000D8519的相同对象ID上进行操作:

12/14/2012 13:46:03,spid23s,Unknown,waiter id=process8cf948 mode=X requestType=wait
12/14/2012 13:46:03,spid23s,Unknown,waiter-list
12/14/2012 13:46:03,spid23s,Unknown,owner id=process4cb3708 mode=Sch-M
12/14/2012 13:46:03,spid23s,Unknown,owner-list
12/14/2012 13:46:03,spid23s,Unknown,objectlock lockPartition=0 objid=455743580 subresource=FULL dbid=2 objectname=tempdb.dbo.#PB_Cost_Excp_Process_Invoices_Work_________________________________________________________________________________0000000D8519 id=lock371705d00 mode=Sch-M associatedObjectId=455743580
12/14/2012 13:46:03,spid23s,Unknown,waiter id=process4cb3708 mode=Sch-M requestType=wait
12/14/2012 13:46:03,spid23s,Unknown,waiter-list
12/14/2012 13:46:03,spid23s,Unknown,owner id=process8cf948 mode=IX
12/14/2012 13:46:03,spid23s,Unknown,owner-list
12/14/2012 13:46:03,spid23s,Unknown,objectlock lockPartition=3 objid=455743580 subresource=FULL dbid=2 objectname=tempdb.dbo.#PB_Cost_Excp_Process_Invoices_Work_________________________________________________________________________________0000000D8519 id=lock3139b4780 mode=IX associatedObjectId=455743580
12/14/2012 13:46:03,spid23s,Unknown,resource-list
12/14/2012 13:46:03,spid23s,Unknown,Proc [Database Id = 8 Object Id = 1857974987]
12/14/2012 13:46:03,spid23s,Unknown,inputbuf
12/14/2012 13:46:03,spid23s,Unknown,EXEC PB_ProcessExc_Costs_Submit_SP @SiteKey, @PWDate
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.DR_SubmitPaperwork_SP line=174 stmtstart=12912 stmtend=13018 sqlhandle=0x03000800cb72be6e500434018da000000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,EXEC PB_ProcessExc_Costs_Create_SP

    -- Clean up work table
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.PB_ProcessExc_Costs_Submit_SP line=138 stmtstart=11890 stmtend=12012 sqlhandle=0x03000800428c1f1950f833018da000000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,UPDATE #PB_Cost_Excp_Process_Invoices_Work
    SET PBCEPrcInv_RtlPkg_Item_Quantity = RtlPkg_Item_Quantity
    FROM #PB_Cost_Excp_Process_Invoices_Work
        INNER JOIN Item_Packages (NOLOCK)
            ON PBCEPrcInv_ItemPkg_Key = ItemPkg_Key
        INNER JOIN Retail_Packages (NOLOCK)
            ON ItemPkg_RtlPkg_Key = RtlPkg_Key

    -- Lookup pricebook cost
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.PB_ProcessExc_Costs_Create_SP line=25 stmtstart=2394 stmtend=3050 sqlhandle=0x030008003a082846321f46018da000000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,executionStack
12/14/2012 13:46:03,spid23s,Unknown,process id=process8cf948 taskpriority=0 logused=0 waitresource=OBJECT: 2:455743580:0  waittime=3739 ownerId=707053534 transactionname=UPDATE lasttranstarted=2012-12-14T13:45:59.327 XDES=0x3c4502930 lockMode=X schedulerid=4 kpid=7276 status=suspended spid=72 sbid=0 ecid=0 priority=0 trancount=2 lastbatchstarted=2012-12-14T13:45:58.337 lastbatchcompleted=2012-12-14T13:45:58.337 clientapp=PDI WCF Services - pdidb01-PDIMaster.cfg hostname=PDIWEB01 hostpid=2084 loginname=pdiuser isolationlevel=read committed (2) xactid=707053534 currentdb=8 lockTimeout=4294967295 clientoption1=673316896 clientoption2=128568
12/14/2012 13:46:03,spid23s,Unknown,Proc [Database Id = 8 Object Id = 1857974987]
12/14/2012 13:46:03,spid23s,Unknown,inputbuf
12/14/2012 13:46:03,spid23s,Unknown,EXEC PB_ProcessExc_Costs_Submit_SP @SiteKey, @PWDate
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.DR_SubmitPaperwork_SP line=174 stmtstart=12912 stmtend=13018 sqlhandle=0x03000800cb72be6e500434018da000000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,EXEC dbo.PB_ProcessExc_Costs_CreateInvoiceWorkTable_SP
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.PB_ProcessExc_Costs_Submit_SP line=58 stmtstart=5782 stmtend=5894 sqlhandle=0x03000800428c1f1950f833018da000000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,ALTER TABLE #PB_Cost_Excp_Process_Invoices_Work DROP COLUMN PBCEPrcInv_Filler
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.PB_ProcessExc_Costs_CreateInvoiceWorkTable_SP line=50 stmtstart=5382 stmtend=5538 sqlhandle=0x0300080025d75a14ffff4701969f00000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,executionStack
12/14/2012 13:46:03,spid23s,Unknown,process id=process4cb3708 taskpriority=0 logused=0 waitresource=OBJECT: 2:455743580:3  waittime=3739 ownerId=707052778 transactionname=ALTER TABLE lasttranstarted=2012-12-14T13:45:58.517 XDES=0x5f48bce80 lockMode=Sch-M schedulerid=6 kpid=7212 status=suspended spid=63 sbid=0 ecid=0 priority=0 trancount=1 lastbatchstarted=2012-12-14T13:45:58.513 lastbatchcompleted=2012-12-14T13:45:58.513 clientapp=PDI WCF Services - pdidb01-PDIMaster.cfg hostname=PDIWEB01 hostpid=2084 loginname=pdiuser isolationlevel=read committed (2) xactid=707052778 currentdb=2 lockTimeout=4294967295 clientoption1=673316896 clientoption2=128568
12/14/2012 13:46:03,spid23s,Unknown,process-list
12/14/2012 13:46:03,spid23s,Unknown,deadlock victim=process4cb3708
12/14/2012 13:46:03,spid23s,Unknown,deadlock-list

更新

有问题的计算机在任务管理器和设备管理器中显示16个处理器,因此启用了锁分区,并且两个锁位于不同的锁分区上。我不知道锁分区是否是造成这种情况的原因。

我还在CSS SQL Server工程师博客上找到了这个有趣的帖子

更新2

临时表在每个存储过程的末尾删除。它们是使用模式create #table,修改架构,插入,更新,选择然后删除来创建的。使用此temp #table的公用过程有多个入口点,因此我们有一个中央proc来设置调用公用proc所需的列。否则,我们必须在所有入口点proc中复制相同的#table定义。

该过程经常从多个客户端应用程序中调用。一些客户端应用程序从多个线程调用此过程。其他人一次运行一次。想一想库存/会计软件,其中家庭办公室正在并行处理数千个商店的数据,而商店自己也运行相同的过程。因此,如果在启用锁分区时这是一个罕见的问题,那么在我们更大的客户数据库上就不会那么罕见了。

更新3-2012-12-19

另一个客户在SQL Server 2012内部版本11.0.2100上遇到相同的问题。在累积更新说明中,我没有看到任何针对此问题的修复程序。研究中。

更新4-2013-02-13

Microsoft已在以下更新中发布了针对此错误的修复程序:


@AaronBertrand:不,我们不要#temp表缓存。在同一连接上这将是非常糟糕的-更少地在进程之间重用。我没有.xdl文件,只有跟踪标志1222信息。
保罗·威廉姆斯

完成后,我们将明确删除这些#temp表。
保罗·威廉姆斯

2
我仍然建议捕获.xdl文件并将其发布在某个位置,以便其他人可以更仔细地查看-它将具有更好的细节。
亚伦·伯特兰

2
我可以确认这里涉及锁分区。这些文章提供了有关分析涉及锁分区和由于锁分区导致的死锁的一些详细信息。 bit.ly/Ruzmym bit.ly/W7yuRK 但是我不知道为什么两个会话都发布相同的ObjectID。
Roji P Thomas

@SQLKiwi感谢您查看问题!我没有考虑过锁定资源哈希。鉴于它位于对象ID上,我怀疑不是这种情况,但我只是在猜测。客户已经向我们报告了僵局数天。我只有1天的死锁跟踪值,但是我敢打赌这是他们一直遇到的死锁。我们正在与Microsoft一起提供支持票证,以帮助我们解决问题。当我了解更多信息时,我将更新此问题。
保罗·威廉姆斯

Answers:



4

我们已与Microsoft就此问题开了一个案子。Microsoft确认此错误也影响SQL Server2012。他们计划在SQL Server 2012 Service Pack 2中发布此修补程序(在我编写此答案时尚未发布)。

在Microsoft发布此Service Pack之前,SQL Server 2012用户可以通过通过跟踪标志1229禁用锁分区来绕过此问题。

请注意,此问题仅适用于具有16个或更多处理器的计算机。

有关锁分区的更多信息

感谢微软的支持!他们非常迅速和乐于助人。

更新

该错误已在SQL Server 2012 SP1的SQL Server 2012累积更新2中修复。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.