sql >> データベース >  >> RDS >> Sqlserver

SQLデッドロックの質問

    SELECT は共有ロックのみを取得するため、他の SELECT とデッドロックすることはありません。あなたは、これらの SELECT が「排他的読み取りロックを必要とする」ことを考慮すべきだとおっしゃいましたが、1) exlusive read lockのようなものがないため、これを考慮することはできません。 2) 読み取りは排他ロックを取得しません。

    しかし、単純なステートメントがデッドロックになる可能性があるかどうかという、より一般的な質問を提起します。答えは明確なYESです .ロックは実行時に取得されます。前もって分析され、ソートされてから、ある順序で取得されるわけではありません。ロックはディスク上の実際のデータに依存するため、エンジンが必要なロックを前もって知ることは不可能であり、エンジンがデータをロックするために必要なデータを読み取ることは不可能です。

    単純なステートメント間のデッドロック (SELECT と UPDATE または SELECT と DELETE) は、インデックス アクセス順序の違いによるもので、非常に一般的であり、調査、診断、および修正が非常に簡単です。ただし、常にあることに注意してください 読み取りは互いにブロックできないため、書き込み操作が含まれます。この説明では、UPDLOCK または XLOCK ヒントを SELECT に追加することは、書き込みと見なす必要があります。 JOIN も必要ありません。セカンダリ インデックスによってアクセス順序の問題が発生し、デッドロックが発生する可能性があります。読み取り/書き込みデッドロック .

    そして最後に、 SELECT FROM A JOIN B を書きます または SELECT FROM B JOIN A と書く はまったく関係ありません。クエリ オプティマイザーは、適切と思われるアクセス順序を自由に再配置できます。クエリの実際のテキストによって実行順序が強制されることはありません。

    更新

    残念ながら、クッキーカッターのレシピはありません。解決策はケースバイケースです。最終的に、データベース アプリケーションでは、デッドロックは日常茶飯事です。 「私たちは月に着陸したが、正しいデータベース アプリケーションを作成することはできません」のように、これがばかげているように聞こえるかもしれませんが、アプリケーションが最終的にデッドロックに遭遇することをほぼ保証する強力な要因が作用しています。幸運なデッドロックは エラーに対処するのが最も簡単で、単純に状態を再度読み取り、ロジックを適用し、新しい状態を書き直します。そうは言っても、デッドロックの頻度を劇的に減らし、ほぼ完全になくすことができるいくつかの優れたプラクティスがあります。

    • 書き込みの一貫したアクセス パターンを持つようにしてください . 「トランザクションは常に次の順序でテーブルを作成する必要があります:Customers」などのルールを明確に定義します。 -> OrderHeaders -> OrderLines .' トランザクション内で順序に従わなければならないことに注意してください .基本的に、すべてをランク付けします スキーマ内のテーブルを変更し、すべての更新がランキング順に発生する必要があることを指定します。これは最終的に、コードを書いている個々の貢献者のコード規律に帰着します。トランザクション内で適切な順序で更新されていることを確認する必要があるからです。
    • 持続時間を短くする の書き込み。通常の知恵は次のとおりです。トランザクションの開始時にすべての読み取りを行い (既存の状態を読み取ります)、ロジックを処理して新しい値を計算し、トランザクションの最後にすべての更新を書き込みます。 'read->write->logic->read->write' のようなパターンは避け、代わりに 'read->read->logic->write->write' を実行します。もちろん、真の職人技とは、しなければならないと思われる実際の、実際の、個々のケースに対処する方法にあります。 トランザクション中に書き込みを行う必要があります。ここで、特定のタイプのトランザクションについて特記しておく必要があります。つまり、定義上、キューからデキュー (=書き込み) することによってアクティビティを開始する、キューによって駆動されるトランザクションです。これらのアプリケーションは常に作成が難しく、エラー (特にデッドロック) が発生しやすいことで知られていましたが、幸いにもそれを行う方法があります。テーブルをキューとして使用する .
    • 読み取りの量を減らします。テーブル スキャンは デッドロックの最も一般的な原因。適切なインデックス作成により、デッドロックが解消されるだけでなく、プロセスのパフォーマンスも向上する可能性があります。
    • スナップショット分離 .これは、デッドロックを回避するという点で、無料のランチに最も近いものです。 マスクする可能性があるため、意図的に最後に配置しました それらを修正する代わりに、他の問題 (不適切なインデックス作成など)。

    LockCustomerByXXX でこの問題を解決しようとしています 私が恐れているアプローチは機能しません。悲観的ロックはスケーリングしません。 オプティミスティック コンカレンシー 更新は まともなパフォーマンスが必要な場合は、ぜひお試しください。



    1. MySQLINT主キーのインデックスの再作成とAUTO_INCREMENTのリセット

    2. テーブルの列の順序について心配する理由はありますか?

    3. MySQLでインデックスのサイズを把握する方法

    4. UPDLOCK で上位 1 を選択し、READPAST でテーブル全体に排他ロックを設定します