sql-server-2005 – SQL Server更新语句导致死锁

我有一个应用程序,它在不同的线程中同时运行多个sql语句,导致各种死锁,这些死锁似乎都来自一个表.例如,下面的两个更新语句:

UPDATE WF SET QUEUETIME =’2011-02-18 13:06:53.578′,STATE =’outbound’,USER =”,TIME = null
WHERE PID =’MessageProcessing’和ACTIVITYID =’删除’和ITEMID =’120’和TRANID =’创建’AND STATE =’ready’AND USER =”

UPDATE WF SET QUEUETIME =’2011-02-18 13:06:53.625′,STATE =’ready’,USER =”,TIME = null
WHERE PID =’standardOutbound’和ACTIVITYID =’Node1’AND ITEMID =’121’AND TRANID =’toNode1’AND STATE =”AND USER =”

产生以下死锁:

<deadlock-list>
 <deadlock victim="process6d8e38">
  <process-list>
   <process id="process6d8e38" taskpriority="0" logused="272" waitresource="RID: 7:1:564:14" waittime="625" ownerId="430343" transactionname="implicit_transaction" lasttranstarted="2011-02-18T13:06:53.640" XDES="0xb44a258" lockMode="U" schedulerid="1" kpid="2632" status="suspended" spid="58" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2011-02-18T13:06:53.640" lastbatchcompleted="2011-02-18T13:06:53.640" clientapp="jTDS" hostname="INTERWOV-FP1" hostpid="123" loginname="database1" isolationlevel="read committed (2)" xactid="430343" currentdb="7" TIMEout="4294967295" clientoption1="671088672" clientoption2="128058">
    <executionStack>
     <frame procname="adhoc" line="1" stmtstart="336" sqlhandle="0x0200000077e2b21749c20d3ca2ca8d4d89ea5ea29336e03e">
UPDATE WF  SET QUEUETIME =  @P0 , STATE =  @P1 , USER =  @P2 , TIME =  @P3  WHERE PID =  @P4  AND ACTIVITYID =  @P5  AND ITEMID =  @P6  AND TRANID =  @P7  AND STATE =  @P8  AND USER =  @P9     </frame>
    </executionStack>
    <inputbuf>
(@P0 datetime,@P1 nvarchar(4000),@P2 nvarchar(4000),@P3 datetime,@P4 nvarchar(4000),@P5 nvarchar(4000),@P6 int,@P7 nvarchar(4000),@P8 nvarchar(4000),@P9 nvarchar(4000))UPDATE WF  SET QUEUETIME =  @P0 , STATE =  @P1 , USER =  @P2 , TIME =  @P3  WHERE PID =  @P4  AND ACTIVITYID =  @P5  AND ITEMID =  @P6  AND TRANID =  @P7  AND STATE =  @P8  AND USER =  @P9     </inputbuf>
   </process>
   <process id="process8ccb68" taskpriority="0" logused="900" waitresource="RID: 7:1:564:12" waittime="625" ownerId="430341" transactionname="implicit_transaction" lasttranstarted="2011-02-18T13:06:53.623" XDES="0xaeccf48" lockMode="U" schedulerid="2" kpid="312" status="suspended" spid="53" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2011-02-18T13:06:53.640" lastbatchcompleted="2011-02-18T13:06:53.623" clientapp="jTDS" hostname="INTERWOV-FP1" hostpid="123" loginname="database1" isolationlevel="read committed (2)" xactid="430341" currentdb="7" TIMEout="4294967295" clientoption1="671088672" clientoption2="128058">
    <executionStack>
     <frame procname="adhoc" line="1" stmtstart="336" sqlhandle="0x0200000077e2b21749c20d3ca2ca8d4d89ea5ea29336e03e">
UPDATE WF  SET QUEUETIME =  @P0 , STATE =  @P1 , USER =  @P2 , TIME =  @P3  WHERE PID =  @P4  AND ACTIVITYID =  @P5  AND ITEMID =  @P6  AND TRANID =  @P7  AND STATE =  @P8  AND USER =  @P9     </frame>
    </executionStack>
    <inputbuf>
(@P0 datetime,@P1 nvarchar(4000),@P2 nvarchar(4000),@P3 datetime,@P4 nvarchar(4000),@P5 nvarchar(4000),@P6 int,@P7 nvarchar(4000),@P8 nvarchar(4000),@P9 nvarchar(4000))UPDATE WF  SET QUEUETIME =  @P0 , STATE =  @P1 , USER =  @P2 , TIME =  @P3  WHERE PID =  @P4  AND ACTIVITYID =  @P5  AND ITEMID =  @P6  AND TRANID =  @P7  AND STATE =  @P8  AND USER =  @P9     </inputbuf>
   </process>
  </process-list>
  <resource-list>
   <ridlock fileid="1" pageid="564" dbid="7" objectname="database1.dbo.WF" id="lock3a63dc0" mode="X" associatedObjectId="72057594077577216">
    <owner-list>
     <owner id="process6d8e38" mode="X"/>
    </owner-list>
    <waiter-list>
     <waiter id="process8ccb68" mode="U" requestType="wait"/>
    </waiter-list>
   </ridlock>
   <ridlock fileid="1" pageid="564" dbid="7" objectname="database1.dbo.WF" id="lock3a65f40" mode="X" associatedObjectId="72057594077577216">
    <owner-list>
     <owner id="process8ccb68" mode="X"/>
    </owner-list>
    <waiter-list>
     <waiter id="process6d8e38" mode="U" requestType="wait"/>
    </waiter-list>
   </ridlock>
  </resource-list>
 </deadlock>
</deadlock-list>

我意识到一定数量的死锁是不可避免的,应用程序应该处理它们(它确实如此),但我不明白为什么它们应该在这种情况下发生.在我的简单化思想中,这两个语句应该锁定不同的行,即使它们正在更新同一行,也应该等待另一行.

谁能解释为什么它们会导致死锁,或者就如何预防它们提出任何建议?

我们在表上有3个非聚集索引(PID,ACTIVITYID,ITEMID,TRANID),(ITEMID)和(PID,ACTIVITYID). (PID,ACTIVITYID,ITEMID,TRANID)构成主键.我曾尝试(有点盲目地)玩索引,但似乎无济于事.

该应用程序在weblogic和sql server 2005上运行,我在websphere和sql server 2008上重现了死锁.使用oracle数据库时似乎没有发生,但遗憾的是这不是我们客户的选项!

非常感谢能够提供帮助或洞察力的任何人.

最佳答案 问题通常不仅仅是更新,而是选择和更新的组合.考虑场景,其中事务选择某行然后更新它.如果两个此类事务并行运行,则会发生死锁.

最简单的解决方案是在select语句中使用UPDLOCK(以及可选的ROWLOCK)提示;当然只有记录,更新后 – 否则你可能会以缓慢的应用程序结束.

点赞