異なるセッションで同時に実行されているストアド プロシージャによって同時に CRUD された SQL サーバーのテーブルがあります。
|----------------|---------|
| <some columns> | JobGUID |
|----------------|---------|
手順は次のとおりです。
- GUID を生成します。
- 上記の共有テーブルにいくつかのレコードを挿入し、ステップ 1 の GUID でマークします。
- ステップ 2 のすべてのレコードに対していくつかの更新を実行します。
- ステップ 3 のレコードを SP 出力として選択します。
ストアド プロシージャ内のすべての select / insert / update / delete ステートメントにはWHERE JobGUID = @jobGUID
句があるため、プロシージャは手順 2 で挿入したレコードでのみ機能します。共有テーブル。SQL Server プロファイラーからのデッドロック グラフを次に示します。
ロックのエスカレーションは発生しません。すべての DML ステートメントにロック ヒントを追加し(UPDLOCK, ROWLOCK)
たり、プロシージャの本体をトランザクションにラップしたり、さまざまな分離レベルを使用したりしようとしましたが、役に立ちませんでした。共有テーブルに対する同じ RID ロックが引き続き使用されます。
その後、共有テーブルに主キー/ID 列がないことがわかりました。そして、それを追加すると、デッドロックが消えたように見えます:
alter table <SharedTable> add ID int not null identity(1, 1) primary key clustered
主キー列を削除すると、デッドロックが再発します。追加し直すと、デッドロックを再現できなくなります。
問題は、主キー ID 列が本当にデッドロックを解決できるのか、それとも単なる偶然なのかということです。
更新: @Catcallが示唆するように、既存の列に (ID 列を追加せずに) 自然にクラスター化された主キーを作成しようとしましたが、それでも同じデッドロックが発生しました (もちろん、今回は RID ロックではなくキーロックでした) )。