私は愚かな質問をしていないことを確認するために、インターネット上のデッドロックに関する大量の情報を読みました。デッドロックが発生する次の表は、注文キューとして機能します。レコードは実際には削除されず、ステータスのみが変更されます (PROCESSING、CANCELLED、COMPLETED など)。SELECTs with UPDLOCK
このテーブルで不可解なデッドロックが発生しています。SELECT について私が目にする唯一の特徴は、内部にあることです。SELECT without UPDLOCK
、しかしそれは問題ではありません。テーブルで行ロックが有効になっています。これらの SELECT は、別々のジョブ スケジューラによって並行して実行されます。このような SELECT の意味は、1 つ以上の指定されたステータス (前述の「PROCESSING、CANCELLED、COMPLETED」) を持つ最初の (最も早い) 注文を取得することです。最小 ID の注文 (最小 ID は手動で選択され、以下のクエリでは 6850000 です) が「最初の」注文と見なされます。これは、パフォーマンス上の理由から行われます。これが実際の SELECT です。
select * from TORDERSUMMARY with (updlock, rowlock)
where ID in
(select min(ID) from TORDERSUMMARY
where ID > 6850000 and (ORDERSTATUS in ( 'INITIATED' ))
and (ORDERDISPATCHSTATUS in ( 0 , 2 , 4 )) and (ORDERGROUPID is null))
テーブルの主キー ID にクラスター化インデックスが定義されています。SQL Server Management Studio 2008 で示されているように、このようなクエリの推定および実際の実行計画は CLUSTERED INDEX SEEK です。テーブルには多数の非クラスター化インデックスがあり、NC インデックス操作がクラスター化インデックス操作でデッドロックすることを望んでいました (ネット上でそのような多くのケースについて詳しく読んだことがあります)。最適な方法 (インデックス シーク) で使用されている場合、原因はそこにあるようには見えません。
内側の SELECT には UPDLOCK、ROWLOCK ヒントがないため、ロックで複数のレコードが選択されることはありません。そのような 2 つの選択がデッドロックになるシナリオは想像できません。もちろん、UPDLOCK ヒントは、コードが後で注文のステータスを更新しようとするためです (処理済みとしてマークするなど)。
これは、SQL Server Management Studio 2008 のデッドロック XDL ファイルの 1 つ ( http://pastebin.com/ugCUbn80 )です。サーバー自体は 9.0.4035 です。SQL クエリは長いため、何らかの理由で XDL ファイルで切り捨てられますが、SELECT は確かに上記のタイプです。そのような SELECT を使用してサーバーの手動ストレス テストを行ったところ、同じクエリでデッドロックがランダムに発生しているように見えるためです。仕方。