MySQL InnoDB ロックの概要

MySQL InnoDB ロックの概要

1. 共有ロックと排他ロック

共有ロック

排他ロック

InnoDB は、共有ロックと排他ロックの 2 種類のロックを含む標準の行レベル ロックを実装します。

共有 (S) ロックは、ロックを保持しているトランザクションが行を読み取ることを許可します。

排他 (X) ロックは、ロックを保持するトランザクションが行を更新または削除することを許可します。

共有ロックにより、ロックを保持しているトランザクションは行を読み取ることができます。

排他ロックにより、ロックを保持しているトランザクションは行を更新または削除できるようになります。

トランザクション T1 が行 r に対して共有ロック (S) を保持している場合、別のトランザクション T2 からの要求は次のように処理されます。

  • T2 の S ロック要求は直ちに許可されます。その結果、T1 と T2 の両方が行 r に対して S ロックを保持します。
  • T2 の X ロック要求はすぐには許可されません。

トランザクション T1 が行 r に対して排他ロック (X) を保持している場合、別のトランザクション T2 からの要求に対して、r に対するどちらのタイプのロックもすぐに付与することはできません。代わりに、トランザクション T2 は、トランザクション T1 が行 r のロックを解除するまで待機する必要があります。

2. 意図ロック

意図ロック

InnoDB はマルチ粒度ロックをサポートしており、行ロックとテーブルロックの共存が可能です。 たとえば、LOCK TABLES ... WRITE などのステートメントは、指定されたテーブルに対して排他ロック (X ロック) を取得します。複数の粒度レベルでロックを実装するために、InnoDB はインテンション ロックを使用します。インテンション ロックは、テーブル レベルのロックであり、トランザクションに対して、後でテーブル内の行に使用する必要があるロックの種類 (共有または排他) を示します。

インテンションロックには 2 つの種類があります。

  • 意図的共有ロック (IS) は、トランザクションがテーブル内の単一行に共有ロックを設定することを意図していることを示します。
  • 意図的排他ロック (IX) は、トランザクションがテーブル内の 1 つの行に排他ロックを設定することを示します。

たとえば、SELECT ... LOCK IN SHARE MODE は IS ロックを設定し、SELECT ... FOR UPDATE は IX ロックを設定します。

意図ロックの合意は次のとおりです。

トランザクションがテーブル内の行に対して共有ロックを取得する前に、まずテーブルに対して IS ロックまたはより強力なロックを取得する必要があります。
トランザクションがテーブル内の行の排他ロックを取得する前に、まずそのテーブルで IX ロックを取得する必要があります。
テーブルレベルのロック タイプの互換性は次のとおりです。

要求元のトランザクションが既存のロックと互換性がある場合はロックが許可されますが、既存のロックと競合する場合はロックは許可されません。トランザクションは、競合する既存のロックが解除されるまで待機します。ロック要求が既存のロックと競合し、デッドロックが発生するため許可できない場合は、エラーが発生します。

意図ロックは、テーブル全体のリクエスト (LOCK TABLES ... WRITE など) 以外をブロックしません。意図的ロックの主な目的は、誰かがテーブル内の行をロックしている、またはロックしようとしていることを示すことです。

3. レコードロック

レコードロック

レコード ロックは、インデックス レコードに対するロックです。

レコード ロックは、インデックス レコードに対するロックです。たとえば、SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; は、t.c1 の値が 10 である行を他のトランザクションが挿入、更新、または削除することを防ぎます。

レコード ロックは、テーブルにインデックスが定義されていない場合でも、常にインデックス レコードをロックします。テーブルにインデックスがない場合、InnoDB は非表示のクラスター化インデックスを作成し、そのインデックスをレコードのロックに使用します。

4. ギャップロック

ギャップロック

ギャップ ロックは、インデックス レコード間のギャップに対するロック、または最初のインデックス レコードの前または最後のインデックス レコードの後のギャップに対するロックです。

ギャップ ロックは、インデックス レコード間のギャップに対するロック、または最初のインデックス レコードの前または最後のインデックス レコードの後のギャップに対するロックです。

たとえば、SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE; は、範囲内のすべての既存の値間のギャップがロックされるため、列に既にそのような値があるかどうかに関係なく、他のトランザクションが t.c1 列に値 15 を挿入することを防ぎます。

ギャップは、単一のインデックス値、複数のインデックス値にまたがる場合があり、空になる場合もあります。

ギャップ ロックは、パフォーマンスと同時実行性のトレードオフの一部であり、一部のトランザクション分離レベルで使用されますが、他のレベルでは使用されません。

一意の行を検索するために一意のインデックスを使用して行をロックするステートメントの場合、ギャップ ロックは必要ありません。

たとえば、id 列に一意のインデックスがある場合、次のステートメントは、他のセッションが前のギャップに行を挿入するかどうかに関係なく、id 値が 100 の行に対してのみインデックス レコード ロックを取得します。

SELECT * FROM child WHERE id = 100;

id 列にインデックスがないか、一意でないインデックスがある場合、ステートメントは先頭のギャップをロックします。

ここで注目すべき点は、異なるトランザクションがギャップに対して競合するロックを保持する可能性があることです。

たとえば、トランザクション A はギャップに対して共有ギャップ ロック (ギャップ S ロック) を保持し、トランザクション B は同じギャップに対して排他ギャップ ロック (ギャップ X ロック) を保持できます。競合するギャップ ロックを許可する理由は、レコードがインデックスから削除された場合、異なるトランザクションによって保持されているレコードのギャップ ロックをマージする必要があるためです。

InnoDB におけるギャップ ロックの唯一の目的は、他のトランザクションがギャップに挿入されるのを防ぐことです。ギャップロックは共存できます。あるトランザクションによって取得されたギャップ ロックは、別のトランザクションが同じギャップに対してギャップ ロックを取得することを妨げるものではありません。共有間隔ロックと排他間隔ロックの間に区別はありません。それらは互いに競合せず、同じ機能を実行します。

5. ネクストキーロック

ネクストキー ロックは、インデックス レコードに対するレコード ロックと、インデックス レコードの前のギャップに対するギャップ ロックの組み合わせです。

ネクストキー ロックは、インデックス レコードのレコード ロックとインデックス レコードの前のギャップ ロックの組み合わせです。

InnoDB が行レベルのロックを行う方法は、テーブル インデックスを検索またはスキャンするときに、検出されたインデックス レコードに共有ロックまたは排他ロックを設定するというものです。したがって、行レベルのロックは実際にはインデックス レコード ロックです。インデックス レコードの次のキー ロックは、そのインデックス レコードの前の「ギャップ」にも影響します。つまり、次のキー ロックは、インデックス レコード ロックと、インデックス レコードの前のギャップ ロックを組み合わせたものになります。セッションがインデックス内のレコード R に対して共有ロックまたは排他ロックを持っている場合、別のセッションはインデックス順序で R の前のギャップに新しいインデックス レコードを挿入できません。

インデックスに値 10、11、13、20 が含まれているとします。このインデックスの可能な次のキー ロックは、次の範囲をカバーします。

(負の無限大、10]
(10、11]
(11、13)
(13、20)
(20、正の無限大)

デフォルトでは、InnoDB は REPEATABLE READ トランザクション分離レベルを使用します。この場合、InnoDB はファントム行を防ぐために、検索とインデックス スキャンに次のキー ロックを使用します。

6. 意図ロックを挿入する

意図ロックを挿入する

挿入意図ロックは、行が挿入される前に INSERT 操作によって設定されるギャップ ロックです。このロックは、複数のトランザクションが同じインデックス ギャップに挿入する場合、ギャップ内の同じ位置に挿入していない限り、トランザクションが互いに待機する必要がないことを意味します。値が4と7のインデックスレコードがあると仮定します。別々のトランザクションが値 5 と 6 を挿入しようとします。各トランザクションは、挿入された行の排他ロックを取得する前に、挿入意図ロックを使用して 4 と 7 の間のギャップをロックしますが、行は競合しないため、互いにブロックされません。

7. AUTO-INCロック

AUTO-INC ロックは、AUTO_INCREMENT 列を持つテーブルに挿入するトランザクションによって取得される特別なテーブル レベルのロックです。最も単純なケースでは、1 つのトランザクションがテーブルに値を挿入している場合、他のトランザクションは、最初のトランザクションによって挿入された行が連続した主キー値を受け取るように、そのテーブルへの独自の挿入を待機する必要があります。

ロックの適用

上記はMySQL InnoDBロックの詳細な概要です。MySQL InnoDBロックの詳細については、123WORDPRESS.COMの他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • MySQL InnoDB トランザクション ロック ソースコード分析
  • MySQL InnoDB のロック機構の詳細な説明
  • MySQL の InnoDB ストレージ エンジンのロックの基本的な使用方法のチュートリアル
  • MySQL の InnoDB のギャップロック問題
  • MySQL InnoDB のロック分類の紹介
  • MySQL InnoDB トランザクションとロックの詳細な説明
  • MySQLのInnoDBストレージエンジンにおけるさまざまなロックの詳細な説明

<<:  Webフロントエンド開発CSS関連チームコラボレーション

>>:  CSS コンテンツ属性を使用して、マウスホバープロンプト (ツールチップ) 効果を実現します。

推薦する

MySQLの文字列インターセプト関連関数の概要

この記事では、MySQL の文字列インターセプト関連の機能を紹介します。具体的な内容は以下のとおりで...

MySQL のメモリ使用量と CPU 使用率が高い場合のテストと解決策

変更後: innodb_buffer_pool_size=576M ->256M InnoDB...

DockerにRedisをインストールし、設定ファイルとして起動する詳細な説明

更新: 最近、サーバーがマイニング ウイルスによってハッキングされたことが判明しました。これは、おそ...

Docker クリーンアップ環境操作

丁寧に掃除を始めましょう!未使用ボリュームの一覧docker ボリューム ls -qf dangli...

Virtualbox で Ubuntu 16.04 の起動時に共有ディレクトリを自動的にマウントする最良の方法

仮想マシンを使用する人は通常、操作と使用を容易にするために仮想マシン用の共有ディレクトリを設定します...

WINDOWS での MYSQL のインストールに関する詳細なチュートリアル

1. インストールパッケージをダウンロードする- お使いのコンピュータシステムに応じて適切なバージョ...

Dockerコマンドの学習を1つの記事にまとめる

目次導入ミラーリポジトリログイン引く押す検索ローカル画像管理画像rmiタグ建てる歴史保存負荷輸入コン...

Vueはシンプルなショッピングカートの例を実装します

この記事では、参考までに、Vue の具体的なコードを共有して、簡単なショッピングカートを実装します。...

MySQL データベースのデータ テーブルの最適化、外部キーの分析、3 つのパラダイムの使用

この記事では、例を使用して、MySQL データベースのデータ テーブルの最適化、外部キーの使用、およ...

HTMLにスクリプトを追加する2つの方法と注意点

HTML に <script> スクリプトを追加する方法: 1. HTMLにJavaSc...

zk+kafka+storm クラスターの docker-compose デプロイメントの実装

クラスターの展開の概要172.22.12.20 172.22.12.21 172.22.12.22 ...

Linux CentOS 7.7 システムの VMware インストールに関する詳細なチュートリアル

Linux CentOS 7.7 システムを Vmware にインストールする方法。最小限のインスト...

MySQL における SQL ページングクエリのいくつかの実装方法と利点と欠点

【SQL】SQLページングクエリの概要開発プロセスではページングが必要になることがよくあります。今日...

CSS カウンターを使用して数字の順序付きリストを美しく表示する方法

Web デザインでは、Web サイトに表示されるデータの構造とコンテンツをユーザーが明確に理解できる...

Docker コンテナの uid と gid の詳細な理解

デフォルトでは、コンテナ内のプロセスは root ユーザー権限で実行され、この root ユーザーは...