行レベルのロックは通常、トランザクションの整合性を確保するために使用する必要があり、これも一般的な理由です。 InnoDB エンジンを選択するための 1 つ。ただし、個々のケースでは、テーブルレベルのロックも必要になる場合があります。
トランザクションは大部分またはすべてのデータを更新する必要があり、テーブルは比較的大きいです。デフォルトの行ロックが使用されている場合、トランザクションの実行効率が低いだけでなく、他のトランザクションが発生する可能性があります。長時間待機し、ロックの競合が発生します。トランザクションには複数のテーブルが含まれます。これはより複雑で、デッドロックや多数のトランザクションのロールバックを引き起こす可能性があります。
取得したい場合テーブル ロックを取得するには、次のコマンドを実行します。
テーブル ロックを使用する場合、効率の問題が発生します。
共有ロックを取得するにはテーブルに S または排他ロック X を設定する場合は、まずテーブルが他のトランザクションによって取得されていないことを確認する必要があります。X ロックの後、このテーブルのデータは他のトランザクションによって取得されていません。
このテーブルに 1,000 万のデータがあると仮定します。これらの 1,000 万のデータのどの行に X ロックがあるかをどのように判断するのでしょうか?
テーブルの S ロックを取得したい場合は、テーブル内のどの行が X ロックを持つかを決定する必要があります。一部の行に X ロックがある場合、このテーブルの S ロックまたは X ロックを取得することはできません。 1 つずつチェックする以外に良い方法はありませんが、これは効率が悪いという問題につながります。行ロックが追加されましたが、問題はほとんどありません。ここで学習しているインテンション共有ロックとインテンション排他ロックは解決できます。
でロックするだけです。 2. インテンション共有ロックとインテンション排他ロック
トランザクション プランはレコードに行共有ロックを追加します。 、トランザクションがレコードの行に共有ロックを追加する前に、まずテーブル
の IS ロックを取得する必要があります。トランザクション プランは、IS ロック行排他ロックにレコードを追加します。トランザクションは行レコードに排他ロックを追加する前に、まずテーブル
です。競合はありません。これは主に、他のユーザーがテーブル ロックを取得する際の効率を上げるのを支援するためです。
を指します!)
、 はテーブル ロックと行ロックの共存 を調整します。主な目的は、トランザクションが行をロックしているか、または行をロックしようとしていることを示すことです。
トランザクション 1 がテーブルへのデータの 10 行目 X ロックを追加すると、InnoDB ストレージ エンジンはテーブル全体に IX ロックを自動的に追加します。トランザクション 2 がテーブル全体の S ロックを取得しようとすると、別のトランザクションがこのテーブルの IX ロックを取得したことがわかります。これは、このテーブルには X ロックに追加されたデータが存在する必要があることを意味します。その結果、トランザクション 2 では、テーブル全体に S ロックを追加できません。現時点では、トランザクション 2 は待機することしかできず、テーブル S ロックを正常に取得できません。 ロック
3. デッドロック
は発生しません。しかし、InnoDB では、単一の SQL で構成されるトランザクションを除き、徐々にロックが取得される、つまりロックの粒度が比較的小さいため、InnoDB ではデッドロックが発生する可能性があると判断されます。もちろん、複数のテーブルが処理される場合でもデッドロックが発生する可能性があります。 デッドロックの問題は通常、私たち自身によって引き起こされます。マルチスレッド プログラミングにおけるデッドロックの状況と同様に、そのほとんどは、複数のスレッドが複数のロック リソースを取得する順序の違いによって引き起こされ、その結果、デッドロックの問題が発生します。したがって、異なるコード セグメントを使用してデータベース内の複数のテーブルを更新する場合は、ロックの競合によってデッドロックの問題が発生するのを防ぐために、これらのテーブルを同じ順序で更新する必要があります。
2. デッドロックのシナリオと解決策
デッドロックのシナリオは次のとおりです:トランザクション 1 は行ロックを正常に取得しました 1
トランザクション 2 は正常に取得されました行ロック 2....
トランザクション 1 は行ロック 2 を取得できませんでした。ブロックされている間、コミット/ロールバックを実行する方法がなく、行ロック 1
トランザクション 2 を解放できませんでした。行ロック 1 を取得しようとしてブロックされました。ブロック中にコミット/ロールバックを実行する方法はなく、行ロックを解放できません。2
すべてのトランザクションがブロックされ、これは、プロセス内のすべてのスレッドがブロックされ、デッドロックの問題が発生するのと同じです。
デッドロックを解決する方法: 複数のトランザクション/スレッドが複数の同じリソース ロックを取得する場合、同じ順序でリソース ロックを取得する必要があります。
トランザクションがブロックまたはデッドロックされています。Mysqld (MySQL Server デーモン) には、トランザクション ブロックの タイムアウト期間が設定されています。トランザクションは長時間ブロックされず、トランザクションはタイムアウト後に処理され、失敗すると、現在保持されているロックが自動的に解放されます。
手動コミットと反復可能な読み取り分離レベルを設定し、トランザクションを開く
テーブル データを反復可能な形式でクエリします。分離レベルは MVCC によって提供されるスナップショット読み取りを使用し、ロックは行いません。
トランザクション 1 は id=7 で排他ロックを取得し、トランザクション 2 は id= で排他ロックを取得します。 8.
トランザクション 1 が再度 id=8 の排他ロックを取得し、ブロッキングが発生します。
トランザクション 2 が取得します。 id= again The exclusive lock of 7 is block.
この時点で、MySQL Server はデッドロックが発生したことを検出するため、トランザクション 1 のブロックを解除し、トランザクション 1 をロールバックし、行ロックが占有されているため、トランザクション 2 は id=7
ビジネスができるという前提の下で、効率を確保するには、より低い分離レベルを使用してみてください (ダーティ リードは回避する必要があります)
合理的なインデックスを設計し、使用してみてください。データにアクセスするためのインデックス、ロックの正確性を高め、ロック競合の可能性を減らし、同時実行機能を向上させます
同時挿入におけるギャップ ロックの影響を回避できます(実際には、等しいクエリではギャップ ロックも追加されます) 実際の必要性を超えるロック レベルを適用しないでください
以上がMySQL のインテント共有ロック、インテント排他ロック、デッドロックとは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。