プロセスがデッドロックの犠牲者となっている原因


105

Selectを使用したプロセスで、完了までに5〜10分程度の時間がかかります。
現在、MS SQLデータベースエンジンへのヒントとしてNOLOCKを使用していません。
同時に、同じデータベースと同じテーブルに更新と挿入を行う別のプロセスがあります。
最初のプロセスが開始されましたが、最近メッセージで途中で終了します

SQLEXCEPTION:トランザクションは別のプロセスでロックリソース上でデッドロックされ、デッドロックの犠牲者として選択されました。

この最初のプロセスは他のサイトで同じ条件で実行されていますが、データベースが小さいため、問題のselectステートメントの所要時間ははるかに短くなります(30秒程度)。これらの他のサイトでは、これらの他のサイトでデッドロックメッセージが表示されません。また、最初に問題が発生しているサイトでもこのメッセージは表示されませんでしたが、データベースが大きくなるにつれて、何らかのしきい値を超えたに違いないと思います。ここに私の質問があります:

  1. トランザクションの実行に時間がかかるため、関連するプロセスにデッドロックの犠牲者としてフラグが立てられる可能性が高くなります。
  2. NOLOCKヒントを使用して選択を実行すると、問題が解決しますか?
  3. selectステートメントのWHERE句の一部としてチェックされる日時フィールドが原因で、ルックアップ時間が遅くなっているのではないかと思います。このフィールドに基づいてインデックスを作成できますか?それはお勧めですか?

ポイント1に対する部分的な回答:デッドロックとタイムアウトを混同しないでください。タイムアウトが発生した場合は、1つのトランザクションの完了にかかる時間が、他の異常終了の原因である可能性があります。また、デッドロックの対象となっているリソース(インデックスかテーブルか)を知っておくと便利です。
NealB 2011

1
SET DEADLOCK_PRIORITY HIGH ALTER DATABASE dbname SET MULTI_USER;
gstackoverflow 2016年

回答:


128

Q1:トランザクションの実行にかかる時間が原因で、関連するプロセスにデッドロックの犠牲者としてフラグが立てられる可能性が高くなりますか?

いいえ。SELECTはデータを読み取っただけなので犠牲になります。したがって、トランザクションのコストは低くなるため、犠牲として選択されます。

既定では、データベースエンジンは、ロールバックにかかるコスト最も低いトランザクションを実行しているセッションをデッドロックの対象として選択します。または、SET DEADLOCK_PRIORITYステートメントを使用して、デッドロック状態のセッションの優先度を指定できます。DEADLOCK_PRIORITYは、LOW、NORMAL、またはHIGHに設定できます。あるいは、範囲(-10〜10)の任意の整数値に設定できます。

Q2。NOLOCKヒントを使用して選択を実行すると、問題が解決しますか?

いいえ。いくつかの理由により:

Q3。selectステートメントのWHERE句の一部としてチェックされるdatetimeフィールドが原因で、ルックアップ時間が遅くなっているようです。このフィールドに基づいてインデックスを作成できますか?それはお勧めですか?

恐らく。デッドロックの原因は、ほとんど可能性が高い不十分インデックス付きdatabase.10分クエリが、私はあなたのケースでは100%確信していることを、このような狭い条件で許容されるべきであるない許容できます。

99%の信頼度で、更新と競合する大規模なテーブルスキャンによってデッドロックが発生したことを宣言します。まず、デッドロックグラフをキャプチャして原因を分析します。おそらく、データベースのスキーマを最適化する必要があります。変更を行う前に、このトピック「インデックスの設計とサブ記事」をお読みください。


完全な回答ありがとうございます。まだ一つ質問がありますね。なぜ1つの環境でのみデッドロック状態が発生し、別の環境では発生しないのですか?ソフトウェアは同じですが。あなたの答えは、選択クエリを実行する時間の長さは違いをもたらさないことを示唆しており、プロセスが失敗する原因となっているのは選択クエリ自体であるという事実です。しかし、なぜ選択クエリの実行に時間がかかるのですか?
エリオット2011

4
クエリの長​​さは、デッドロックの犠牲者の選択に違いはありません。それは、少なくとも2つの要因によってデッドロックを引き起こすことに違いをもたらします:1)単純な確率。クエリが長いほど、同時更新がオーバーラップしてデッドロックに陥る可能性が高くなります。2)大きなテーブルは、完全に異なるクエリプランを使用する場合があり、デッドロックの影響を受けやすいものです。
Remus Rusanu 2011

12

この特定のデッドロック問題が実際にどのように発生し、実際に解決されたかを以下に示します。これはかなりアクティブなデータベースで、毎日13万件のトランザクションが発生します。このデータベースのテーブルのインデックスは、最初はクラスター化されていました。クライアントから、インデックスを非クラスター化するように要求されました。我々がそうするや否や、行き詰まりが始まった。インデックスをクラスター化して再構築すると、デッドロックが停止しました。


34
なぜ誰かが説明できますか?(魔法のソリューションはあまり役に立ちません)
OGrandeDiEnne 2017年

1
この男は彼の投稿でそれを説明しています: mssqltips.com/sqlservertip/2517/…– siga0984 '17
10/17

6

ここでの答えは試してみる価値がありますが、コードも確認する必要があります。具体的には、ここでPolyfunの回答を読んでください: SQL Server 2005およびC#アプリケーションのデッドロックを取り除く方法は?

同時実行の問題と、クエリでの "with(updlock)"の使用がデッドロックの状況をどのように修正できるかを説明します-実際にコードが何をしているかに依存します。コードがこのパターンに従っている場合は、ダーティリードなどに頼る前に、この修正を行うことをお勧めします。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.