4

SQL Server Profiler を使用してデッドロックの原因を特定しようとしています。デッドロック グラフは次のとおりです。 デッドロック グラフ どちらのステートメントも挿入であり、select scope_identity(); 実際には 2 つの同時プロセスがあり、1 サイクルでinsert-select_identityを繰り返し実行します。

私が期待するのは、挿入がクラスター化されたインデックスに対して排他的ロックを取得し、選択が非クラスター化インデックスの共有ロックを取得し、それぞれのインデックスが解放されるのを待つことです。

私が見ているのは、両方のプロセスが同じリソース (クラスター化インデックス) が解放されるのを待っていることです。どうすればいいの?特定のリソースは、1 つのプロセスまたは別のプロセスに属する必要があります。ここで何が恋しいですか?事前にすべてに感謝します。

編集: はい、分離レベルはシリアライズ可能です。wherePS:おそらく、選択にステートメントが含まれていない限り、非クラスター化インデックスの共有ロックに関する私の仮定は間違っていました

Edit2: ここに xml の一部があります:

 <resource-list>
   <keylock hobtid="72057594148028416" dbid="29" objectname="<confidential>" indexname="PK_WP_Inbound_StockTransactionLine" id="lock9641700" mode="RangeS-S" associatedObjectId="72057594148028416">
    <owner-list>
     <owner id="process8e09288" mode="RangeS-S"/>
    </owner-list>
    <waiter-list>
     <waiter id="process991ce08" mode="RangeI-N" requestType="convert"/>
    </waiter-list>
   </keylock>
   <keylock hobtid="72057594148028416" dbid="29" objectname="<confidential>" indexname="PK_WP_Inbound_StockTransactionLine" id="lock9641700" mode="RangeS-S" associatedObjectId="72057594148028416">
    <owner-list>
     <owner id="process991ce08" mode="RangeS-S"/>
    </owner-list>
    <waiter-list>
     <waiter id="process8e09288" mode="RangeI-N" requestType="convert"/>
    </waiter-list>
   </keylock>
  </resource-list>

これによると、SERIALIZABLE分離によるRangeスキャンだと思います(ググった)。しかし、それでも、これがどのように発生するのか、推奨される解決策は何なのかわかりません。

4

1 に答える 1

6

同じレコードにアクセスする 2 つの並列トランザクション (T1 と T2) から次のコードが呼び出されることを検討してください。

Read LastRow
Insert AtLastRow

コンテキストの切り替えが で発生するとしましょうRead。したがって、一連の操作は

T1 Read LastRow
T2 Read LastRow
T2 Insert AtLastRow // This will wait for T1 to finish.
T1 Insert AtLastRow // This will wait for T2 to finish. Hence deadlock!

上記の読み取りはRange S-Sロックを取得します。Insert at lastには、他のトランザクションが保持する既存のロックRange I-Nと互換性のないものも必要です。Range S-Sしたがって、それは待ちます。

この問題を解決するには、複数の方法があります。

  1. 全体的な分離レベルとしてコミットされた読み取りを使用し、シリアライズできません。これにより、Range ロックを取得できなくなります。
  2. 更新ロック(UPDLOCK)で読み取ります。これにより、排他的な更新ロックが最初に取得されます。したがって、他のトランザクションは Read 自体で待機します。
  3. 読み取りと挿入/更新のパターンは避けてください。挿入/更新をそのまま進めて、失敗させてください。

ご不明な点がございましたら、お知らせください。

于 2012-09-26T07:31:03.497 に答える