複数の行を1つにまとめたSQL Server 2014データベースにアプリケーションを接続しました。アプリケーションの実行中は、このデータベースへの他の接続はありません。SQL Serverのデッドロックの防止
まず、特定の期間内の行のチャンクを選択します。このクエリは、クラスタ化されたルックアップとマージされた非クラスタ化シーク(TIME列)を使用します。
select ...
from FOO
where TIME >= @from and TIME < @to and ...
次に、これらの行をC#で処理し、変更を1回の更新と複数回の削除として書き込みます。これはチャンクごとに何度も発生します。これらは、クラスタ化されていないインデックスシークも使用します。
begin tran
update FOO set ...
where NON_CLUSTERED_ID = @id
delete FOO where NON_CLUSTERED_ID in (@id1, @id2, @id3, ...)
commit
これを複数の並列チャンクで実行すると、デッドロックが発生します。 update
とdelete
にはROWLOCK
を使用しようとしましたが、チャンク間に重複がなくても何らかの理由でこれまで以上にデッドロックが発生しました。
update
でTABLOCKX, HOLDLOCK
を試しましたが、それは私が並列性の利点を失うように私はselect
を並列に実行できないことを意味します。
どのように私はデッドロックを回避できますが、まだ複数の並列チャンクを処理することができますか?
この場合、select
にNOLOCK
を使用することは安全でしょうか。チャンク間に行が重複していないとします。その後、TABLOCKX, HOLDLOCK
はupdate
とdelete
をブロックするだけですか?
デッドロックが発生し、アプリケーションでクエリを再試行することを受け入れるだけでよいですか?
UPDATE(追加情報):すべてのデッドロックは、これまでupdate
とdelete
相、select
でなしに起きています。私は今日解決されない場合、いくつかのデッドロックログを取得しようとします(正しいトレースフラグは以前は有効になっていませんでした)。
UPDATE:これらはROWLOCK
で発生したデッドロックの2つの構成されているが、彼らは両方だけdelete
文と、それが使用する非クラスタ化インデックスを参照してください。私は、これらのものを再現できないため、これらがテーブルのヒントなしで発生するデッドロックと同じかどうかはわかりません。
.XDLから必要な何かがあるのかどうかを尋ね、私は全部を取り付ける少し疲れましたよ。
あなたの選択中に 'UPDLOCK'を主張しようとしましたか?そうすれば、デッドロックからあなたを守るはずです。可能であれば、デッドロックログの詳細を私たちと共有してください。 – Jens
すべての処理をストアドプロシージャに移動できますか?スナップショットの隔離を有効にするだけで解決することもできますが、実際は自分が行っていることに依存します。 –
@Jens残念ながら、今はデッドロックログを取得できません。デッドロックのために失敗したスレッドはすべて 'update'と' delete'フェーズにあったようですので、 'select'ロックを変更することはこのケースに影響することはまずありません。私は残念ながらデッドロックログを持っていないので、次回の試みでデッドロックトレースフラグを有効にできるかどうかを確認します。 @ Nick.McDermaid残念なことに、スナップショットの分離を使用できません。 –