ここに質問と 1 つの回答を投稿します。誰かがより良い答えを持っているかもしれません...
開発者がデータベースへの 2 番目の接続を誤って開いた場合に、既存の接続 (既に開いているトランザクションがある可能性があります) を再利用するのではなく、1 人のユーザーに対してもデッドロックをトリガーするコードを作成することができます。特定の O/RM および LINQ フレームワークでは、この間違いが起こりやすくなっています。
純粋な SQL 用語でのシナリオは次のとおりです。
--Setup:
CREATE TABLE Vendors(VendorID int NOT NULL, VendorName nvarchar(100) NOT NULL, ExtraColumn int not null, CONSTRAINT PK_Vendors PRIMARY KEY CLUSTERED(VendorID))
GO
INSERT INTO Vendors(VendorID,VendorName,ExtraColumn) VALUES (1, 'Microsoft', 12345)
INSERT INTO Vendors(VendorID,VendorName,ExtraColumn) VALUES (2, 'Oracle', 12345)
--Connection 1:
BEGIN TRANSACTION
UPDATE Vendors SET ExtraColumn = 222 WHERE VendorID = 2
--Connection 2:
BEGIN TRANSACTION
SELECT VendorName FROM Vendors WHERE VendorID = 1
このコード (およびそれを生成した c#/java/ORM/LINQ) は、データが小さい場合は開発/テストで問題なく実行される可能性がありますが、運用環境でデータ/メモリ プロファイルが変更され、ロックが行から行にエスカレートすると、突然デッドロックになります。ページからテーブルへ。
では、このようなバグ(コードが 2 番目の接続を開く場所) をフラッシュできるように、テスト環境でテーブル レベルまで強制的にロックをエスカレーションするにはどうすればよいでしょうか?
ロックのエスカレーションは SQL Server データベース エンジンによって完全に制御されており、行ロックからテーブル ロックにエスカレートする時期を予測することはできません。ここで見つけることができるすべての詳細を再ハッシュすることはしませんが、特に注意すべき点は次のとおりです。これは、慎重に作成されたコードや完全に選択されたインデックスとはまったく無関係である可能性があることを意味します。