Sql server 2005 SQL server更新语句导致死锁

Sql server 2005 SQL server更新语句导致死锁,sql-server-2005,sql-update,database-deadlocks,Sql Server 2005,Sql Update,Database Deadlocks,我有一个应用程序,它在不同的线程中同时运行多个sql语句,导致各种死锁,而这些死锁似乎都来自一个表。例如,下面的两个更新语句: 更新WF SET QUEUETIME='2011-02-18 13:06:53.578',STATE='outbound',USER=''',TIME=null 其中PID='MessageProcessing'和ACTIVITYID='Delete',ITEMID='120',TRANID='Created',STATE='ready',USER=' 更新WF SET

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

更新WF SET QUEUETIME='2011-02-18 13:06:53.578',STATE='outbound',USER=''',TIME=null 其中PID='MessageProcessing'和ACTIVITYID='Delete',ITEMID='120',TRANID='Created',STATE='ready',USER='

更新WF SET QUEUETIME='2011-02-18 13:06:53.625',状态='ready',用户='',时间=null 其中PID='standardOutbound',ACTIVITYID='Node1',ITEMID='121',TRANID='toNode1',STATE=''和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>

更新WF SET QUEUETIME=@P0,STATE=@P1,USER=@P2,TIME=@P3,其中PID=@P4和ACTIVITYID=@P5和ITEMID=@P6和TRANID=@P7,STATE=@P8和USER=@P9
(@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))更新WF SET QUEUETIME=@P0,STATE=@P1,USER=@P2,TIME=@P3,其中PID=@P4,ACTIVITYID=@P5,ITEMID=@P6,TRANID=@P7,STATE=@P8,USER=@P9
更新WF SET QUEUETIME=@P0,STATE=@P1,USER=@P2,TIME=@P3,其中PID=@P4和ACTIVITYID=@P5和ITEMID=@P6和TRANID=@P7,STATE=@P8和USER=@P9
(@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))更新WF SET QUEUETIME=@P0,STATE=@P1,USER=@P2,TIME=@P3,其中PID=@P4,ACTIVITYID=@P5,ITEMID=@P6,TRANID=@P7,STATE=@P8,USER=@P9
我意识到一定数量的死锁是不可避免的,应用程序应该处理它们(确实如此),但我不明白为什么会发生这种情况。在我过于简单的想法中,这两条语句应该锁定不同的行,即使它们正在更新同一行,一条语句也应该等待另一条语句

有人能解释一下为什么他们会造成僵局,或者就如何防止僵局给出一些建议吗

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

该应用程序在weblogic和SQLServer2005上运行,我在websphere和SQLServer2008上重现了死锁。使用oracle数据库时似乎不会出现这种情况,但不幸的是,这不是我们客户机的选项


非常感谢任何能够提供帮助或深入了解这一点的人。

问题通常不仅仅是更新,而是选择和更新的组合。考虑场景,其中事务选择某行,然后更新它。如果两个这样的事务并行运行,就会发生死锁。
最简单的解决方案是在select语句中使用UPDLOCK(以及可选的ROWLOCK)提示;当然,仅适用于记录,更新后-否则您可能会以缓慢的应用程序结束。

是否有聚集索引?有索引视图吗?还有其他索引吗?正在更新的列似乎不在任何索引中。行级锁定应该可以,但一定是什么原因导致了升级。这些集合看起来是不相交的,但可能页面是重叠的(因此我的问题是如何选择聚集索引)


Oracle(默认情况下)使用乐观并发-它没有MS SQL的悲观并发锁那么多。如果我要添加一个聚集索引,它应该在所有要更新的列上,还是在where子句中?我们运行的其他查询可能会更新此表中不同列的子集。事务处理似乎已经有X个锁,并且正在尝试获得U个锁,为什么更新已经有X个锁?@LeeH聚集索引应该是唯一的(因此不需要添加非限定元素)、固定宽度(用于确定性存储行为)、狭窄(用于高效存储和工作集)、不可为空(不需要空块)、增加(以最小化页拆分)和静态(以最小化数据移动)-@LeeH和pages overlapping,我的意思是,行位于同一页上,尽管它们在您认为键如何划分空间方面有很大的不同。但是在堆表中,底层数据没有顺序,因此您对其几乎没有控制权。然而,我认为行锁升级为表锁,而无需重新设置不管怎样,还是先打开一个页面锁定。谢谢你的帮助,我真的不知道这意味着什么,但这是一个很好的指针,可以用来指示阅读内容。据我所知,代码正在获取连接,运行单个update语句,然后关闭连接,所以我看不到select将在哪里运行。除非更新以某种方式进行Gger是一个隐式选择?或者我们在weblogic中使用连接池这一事实意味着事务的持续时间比我想象的要长?我在这里非常猜测…@LeeH你是说只有这两个更新同时运行,没有其他读或写活动?如果有读活动,使用快照isolati可以减少争用关于读取,但我通常建议坚持默认的读取提交事务隔离锁级别数据库上可能还有其他活动,但从死锁xdl来看,似乎是这两个更新同时运行导致了问题。我不明白为什么它们在等待U-锁,这对upd正常吗