4

複数の sql ステートメントを異なるスレッドで同時に実行しているアプリケーションがあり、すべてが 1 つのテーブルから発生しているように見えるさまざまなデッドロックを引き起こしています。たとえば、次の 2 つの更新ステートメントは次のとおりです。

UPDATE WF SET QUEUETIME='2011-02-18 13:06:53.578', STATE = 'outbound', USER = '', TIME = null WHERE PID = 'MessageProcessing' AND ACTIVITYID = 'Delete' AND ITEMID = '120' AND TRANID = '作成済み' AND 状態 = '準備完了' AND USER = ''

UPDATE WF SET QUEUETIME='2011-02-18 13:06:53.625', STATE = 'ready', USER = '', TIME = null WHERE PID = 'standardOutbound' AND 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>

ある程度のデッドロックは避けられず、アプリケーションがそれらを処理する必要があることは理解していますが (実際に処理します)、この場合になぜデッドロックが発生するのかわかりません。私の単純な考えでは、これらの 2 つのステートメントは異なる行をロックする必要があり、同じ行を更新していたとしても、一方が他方を待つ必要があります。

デッドロックを引き起こしている理由を説明したり、デッドロックを防ぐ方法について何か提案をしたりできますか?

テーブルには 3 つの非クラスター化インデックス (PID、ACTIVITYID、ITEMID、TRANID)、(ITEMID)、および (PID、ACTIVITYID) があります。(PID、ACTIVITYID、ITEMID、TRANID) が主キーを構成します。私は(やや盲目的に)インデックスをいじってみましたが、一見役に立たないようです。

アプリケーションは weblogic と sql server 2005 で実行されており、websphere と sql server 2008 でデッドロックを再現しました。Oracle データベースを使用している場合は発生しないようですが、残念ながらこれはクライアントのオプションではありません!

これについて助けや洞察を提供できる人に感謝します。

4

2 に答える 2

1

問題は通常、更新だけではなく、選択と更新の組み合わせです。トランザクションが行を選択して更新するシナリオを考えてみましょう。このような 2 つのトランザクションが並行して実行されると、デッドロックが発生します。最も簡単な解決策は、select ステートメントで UPDLOCK (およびオプションで ROWLOCK) ヒントを使用することです。もちろん、後で更新されるレコードのみです。そうしないと、アプリケーションが遅くなる可能性があります。

于 2011-02-22T10:42:43.397 に答える
1

クラスタ化インデックスはありますか? インデックス付きビューはありますか? 他の指標は?更新中の列は、どのインデックスにも含まれていないようです。行レベルのロックは問題ないはずですが、何かがエスカレーションを引き起こしているに違いありません。セットはバラバラに見えますが、ページが重複している可能性があります (したがって、クラスター化インデックスの選択に関する私の質問です)。

http://msdn.microsoft.com/en-us/library/ms184286.aspx

于 2011-02-22T11:36:42.097 に答える