SQL Server 2016に3つのクラスター化列ストアインデックス(CCI)テーブルがあります。これらのCCIはすべて、テナントIDに基づいて同じパーティションスキームにあります。最近、一貫性のない方法で、結合からこれらのテーブルへの単純な選択ステートメントでデッドロックが発生しています。デッドロックするクエリの例:
SELECT TOP 33 r.tenantid
FROM Table_r r
INNER JOIN Table_cm cm ON r.MyKey=cm.MyKey
INNER JOIN Table_pe pe ON r.MyKey=pe.MyKey
WHERE r.TenantId = 69
AND pe.TenantId = 69
AND cm.TenantId = 69
エラーメッセージ:
トランザクション(プロセスID 56)は、別のプロセスで汎用の待機可能なオブジェクトリソースでデッドロックされ、デッドロックの犠牲者として選択されました。トランザクションを再実行します。
手がかり:
- クエリがCCI以外の別のインデックスを使用する場合、デッドロックは発生しません。
- 3つのテナントフィルターのうち2つを削除しても、デッドロックしません。
- トップ32以下を選択しても、デッドロックは発生しません。
- OPTION(MAXDOP 1)を追加しても、デッドロックは発生しません。
- スクランブルされたPRODレプリカ、PROD読み取り専用セカンダリ、およびPROD自体でこれを再現できます。
- この動作をDEVまたはINTで再現できません。
- 3つのテーブル結合すべてにWITH(NOLOCK)を追加すると、依然としてデッドロックが発生します
- クエリ自体がデッドロックします。他にアクティブなプロセスがない場合はデッドロックします。
- 並列処理のないクエリプランはデッドロックしない
PRODバージョン:
Microsoft SQL Server 2016(SP2-CU5)(KB4475776)-13.0.5264.1(X64)Jan 10 2019 18:51:38 Copyright(c)Microsoft Corporation Enterprise Edition(64-bit)on Windows Server 2012 R2 Standard 6.3(Build 9600 :)(ハイパーバイザー)
このクエリのデッドロックを防ぐにはどうすればよいですか?