RDBMSでデッドロックはどのように検出および報告されますか?


8

面接でこのエッセイ型の質問を受けましたが、就職できませんでした。完全な質問は次のとおりです。

RDBMSでデッドロックはどのように検出および報告されますか?トランザクションの所有者とアプリケーション開発者は、検出と防止の両方のシナリオで確認する責任がありますか?

回答:


13

SQL Serverには別のスレッドがあり、定期的に(デフォルトでは5秒、デッドロックが検出された場合は間隔が狭く)サイクルの待機リストをチェックします。つまり、スレッドが待機しているリソースを識別し、そのリソースの所有者を見つけ、そのスレッドが順番に待機しているリソースを再帰的に見つけて、他の各リソースを待機しているスレッドを識別します。

デッドロックが見つかった場合、このアルゴリズムを使用して犠牲者が強制終了されます。

  1. 強制終了できないスレッドを識別します(たとえば、トランザクションをロールバックしているスレッドは強制終了できません)。
  2. デッドロックの優先順位が最も低いスレッドを見つけます。
  3. ロールバックが最も安価なもの、つまり、これまで作業が最も少ないものを選択しました。

あなたはここにSQLサーバーのデッドロック検出に関する詳細な情報を見つけることができます: http://msdn.microsoft.com/en-us/library/ms178104.aspx



トランザクションの所有者/アプリケーション開発者は、デッドロックが発生するリスクを最小限にするための責任がある、とやって彼らがすべきこと:

  1. トランザクションはできるだけ短くしてください。たとえば、トランザクションの開始後にログインフォームを表示せず、ユーザーの入力を待つ代わりに、必要な情報をすべて収集してからトランザクションを実行します。
  2. 可能な限り低い分離レベルを使用します。たとえば、一時的にユーザーにいくつかの値を表示したいだけの場合は、シリアライズ可能に設定しないでください。正しい分離レベルを設定すること自体は科学であり、この回答の範囲外であることに注意してください。
  3. デッドロックの被害者である場合、つまりエラー番号1205が発生した場合は、トランザクションをユーザーに対して透過的に再実行します。もう1つの競合するトランザクションが、待機して終了していたリソースをうまく取得できたので、同じデッドロックが再び発生する可能性はほとんどありません。

4.リソースを取得し、アプリケーション全体で一貫して同じ順序で更新/削除/挿入パターンを実行します。
ErikE

3
@ErikEでは、この疑わしいアドバイスがWebで非常に人気がありますが、「アプリケーション全体で一貫して同じ順序でパターンを更新、削除、挿入する」ことは不可能/不可能です。詳細はこちら:sqlblog.com/blogs/alexander_kuznetsov/archive/2010/01/15/...
AK

1
良い点。しかし、それが常に可能であるか、または常に問題を修正するという幻想がない限り、努力は価値があると私はまだ思います。親/子の事は興味深いですが、最初に親の行のカスケード削除または更新ロックの取得はどうですか?MERGEを使用せずにマージを実行する場合、一貫性がないのはなぜですか?個人的に削除->更新->挿入を行います。
ErikE

1
@AlexKuznetsov:これは解決策の弾丸ではありませんが、却下すべきではありません。私減少しているが(排除しない)のに、このようにデッドロック:私は「時期尚早な最適化は、」などを適用することをお勧めしたい、毎日または7をデッドロックやっ頻繁に実行コードの静的解析を経て
GBN

推奨番号3に同意しません。デッドロック後に再試行すると、他のプロセスの変更が上書きされる可能性が高くなります。他の誰かが、私たちが変更しようとしていたデータを変更した可能性が非常に高いことに注意する必要があります。特に、すべてのリーダーがスナップショット分離で実行されている場合、リーダーはデッドロックに関与できません。つまり、デッドロックに関与するすべての関係者はライターであるか、変更されるか、同じデータを変更しようとします。例外をキャッチして自動的に再試行するだけで、他の誰かの変更を上書きできます。これは失われた更新と呼ばれ、通常これは間違っています。
AK
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.