デッドロック
いわゆるデッドロック: 実行プロセス中に、競合により 2 つ以上のプロセスが相互に待機する現象を指します。資源が原因であり、外力がなければ前進できません。このとき、システムがデッドロック状態にある、またはシステムがデッドロックに陥っているといい、このように常に待ち合っているプロセスをデッドロックプロセスと呼びます。
リソースの占有は相互に排他的であるため、プロセスがリソースを申請すると、関連するプロセスには必要なリソースが割り当てられず、外部の支援なしでは実行を続けることができなくなり、特殊な現象であるデッドロックが発生します。
実行プログラム内の 2 つ以上のスレッドが永続的にブロック (待機) され、各スレッドが他のスレッドによって占有およびブロックされているリソースを待機している状況。たとえば、スレッド A がレコード 1 をロックしてレコード 2 を待機し、スレッド B がレコード 2 をロックしてレコード 1 を待機する場合、2 つのスレッド間でデッドロックが発生します。
コンピュータ システムでは、システムのリソース割り当て戦略が不適切な場合、またはより一般的にはプログラマが作成したプログラムにエラーがある場合など、リソースに対する不適切な競合によりプロセスがデッドロックを引き起こします。
ロックを実装するには、インテンション ロック、共有排他ロック、ロック テーブル、ツリー プロトコル、タイムスタンプ プロトコルなど、さまざまな方法があります。ロックには複数の粒度もあり、たとえば、テーブルまたはレコードをロックできます。
デッドロックの主な理由は次のとおりです。
(1) システム リソースが不十分です。
(2) プロセスの実行順序と進行順序が不適切です。
(3) リソースの不適切な配分等
システムリソースが十分であり、プロセスのリソース要求を満たすことができる場合、デッドロックが発生する可能性は非常に低くなりますが、そうでない場合は、限られたリソースの競合によりデッドロックに陥ります。次に、プロセスの実行順序と速度が異なる場合にもデッドロックが発生する可能性があります。
デッドロックが発生するために必要な 4 つの条件:
(1) 相互排他条件: リソースは一度に 1 つのプロセスしか使用できません。
(2) 要求と保持の条件: リソースの要求によりプロセスがブロックされた場合、取得したリソースは保持されます。
(3) 非剥奪条件: プロセスが獲得したリソースは、使い果たされる前に強制的に剥奪することができません。
(4) ループ待ち条件: 複数のプロセス間で先頭から末尾までのループ待ちリソース関係が形成されます。
これら 4 つの条件はデッドロックの必須条件であり、システム内でデッドロックが発生している限り、これらの条件が成立する必要があり、いずれか 1 つでも満たされない限り、デッドロックは発生しません。
デッドロックの予防と救済:
デッドロックの原因、特にデッドロックを発生させるための 4 つの必要条件を理解することで、デッドロックを可能な限り回避できます。デッドロックを解決します。したがって、システム設計やプロセスのスケジューリングなどの観点から、これら 4 つの必要条件が成立しないようにする方法と、プロセスがシステム リソースを永続的に占有することを避けるための合理的なリソース割り当てアルゴリズムを決定する方法に注意してください。
さらに、プロセスが待機状態にあるときにリソースを占有しないようにする必要もあります。システムの実行プロセス中に、システムが満たせるプロセスによって発行された各リソース要求が動的にチェックされ、リソースを割り当てるかどうかのチェック結果に基づいて決定され、割り当て後にシステムがデッドロックする可能性がある場合は割り当てられず、そうでない場合は割り当てられます。したがって、リソースの割り当ては適切に計画する必要があります。
デッドロックを最小限に抑える方法
デッドロックを完全に回避することはできませんが、デッドロックの数を最小限に抑えることはできます。デッドロックを最小限に抑えると、トランザクションのスループットが向上し、トランザクションによって実行されたすべての作業が元に戻されるトランザクションがほとんどロールバックされないため、システムのオーバーヘッドが削減されます。デッドロックの場合はロールバックのため、アプリケーションによって再送信されます。
次の方法は、デッドロックを最小限に抑えるのに役立ちます。
(1) 同じ順序でオブジェクトにアクセスします。
(2) トランザクションにおけるユーザーの対話を回避します。
(3) トランザクションは短くまとめて実行してください。
(4) 低い分離レベルを使用します。
(5) バインディング接続を使用します。
1. 同じ順序でオブジェクトにアクセスする
すべての同時トランザクションが同じ順序でオブジェクトにアクセスすると、デッドロックの可能性が減ります。たとえば、2 つの同時トランザクションが Supplier テーブルのロックを取得し、次に Part テーブルのロックを取得した場合、一方のトランザクションはもう一方のトランザクションが完了するまで Supplier テーブルでブロックされます。最初のトランザクションがコミットまたはロールバックした後、2 番目のトランザクションが続行されます。デッドロックは発生しません。すべてのデータ変更にストアド プロシージャを使用すると、オブジェクトにアクセスする順序が標準化されます。
2. トランザクションでのユーザー操作の回避
###ユーザー操作なしでバッチを実行する方が、ユーザーが手動でクエリに応答するよりもはるかに高速であるため、ユーザー操作を含むトランザクションの作成を避けてください。リクエストパラメータの入力を求めるプロンプトが表示されます。たとえば、トランザクションがユーザー入力を待っているときにユーザーが昼食に出かけたり、週末に家に帰ったりした場合、ユーザーはトランザクションを一時停止し、トランザクションを完了できません。これにより、トランザクションが保持するロックはトランザクションがコミットまたはロールバックするまで解放されないため、システムのスループットが低下します。デッドロックが発生しない場合でも、同じリソースにアクセスする他のトランザクションはブロックされ、トランザクションが完了するまで待機します。 3. トランザクションは短くまとめて行うデッドロックは通常、複数の長時間実行トランザクションが同じデータベース内で同時に実行されるときに発生します。トランザクションの実行時間が長くなるほど、排他ロックまたは更新ロックが保持される時間が長くなり、他のアクティビティがブロックされ、デッドロックが発生する可能性があります。
トランザクションをバッチ内に保持すると、トランザクションのネットワーク通信往復量を最小限に抑え、トランザクション完了時の遅延の可能性を減らし、ロックを解放できます。
4. 低い分離レベルを使用する
トランザクションを低い分離レベルで実行できるかどうかを決定します。コミットされた読み取りを実行すると、トランザクションは、最初のトランザクションが完了するのを待たずに、別のトランザクションによって読み取られた (変更されていない) データを読み取ることができます。高い分離レベル (Serializable Read など) の代わりに低い分離レベル (Read Committed など) を使用すると、共有ロックが保持される時間が短縮され、ロックの競合が減少します。
5. バインドされた接続を使用する
同じアプリケーションによって開かれた 2 つ以上の接続が相互に連携できるように、バインドされた接続を使用します。セカンダリ接続によって取得されたロックは、プライマリ接続によって取得されたロックと同様に保持でき、その逆も同様であるため、相互にブロックされません。
6. ストアド プロシージャを使用して、デッドロックの原因となったプロセスと SQL ステートメントを特定します。
デッドロックが発生した場合、デッドロックの原因となった SQL ステートメントまたはストアド プロシージャをどのように検出すればよいでしょうか? ?このとき、次のストアド プロシージャを使用すると、デッドロックの原因となったプロセスと SQL ステートメントを検出して特定できます。
関連する推奨事項: 「mysql チュートリアル 」
以上がデータベースデッドロックの原因と解決策は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。