MySQLのロック機構の詳細な説明

MySQLのロック機構の詳細な説明

序文

データの一貫性と整合性を確保するために、あらゆるデータベースにはロック メカニズムが備わっています。ロック機構の長所と短所は、データベース システムの同時処理能力とパフォーマンスに直接関係するため、ロック機構の実装はさまざまなデータベースの中核技術の 1 つになっています。

数か月前、プロジェクトでトランザクションが使用され、強力なデータ一貫性を確保する必要がありました。この時期には MySQL ロックも使用されていましたが、当時は MySQL のロックの仕組みを垣間見ただけだったので、この記事では MySQL のロックの仕組みについてまとめたいと思います。

この記事では主にMySQLのロックメカニズムについて説明します。MySQLのバージョンは5.7、エンジンはInnoDBです。InnoDBロックに関する知識やロック方法は実際にはたくさんあるため、すべてのシナリオでのロックプロセスをリストアップして分析するにはエネルギーが足りません。現在の知識のみに基づき、公式ドキュメントと組み合わせて、私の理解についてお話しします。何か間違っている点が見つかった場合は、ご訂正ください。

概要

一般に、InnoDB には 7 種類のロックがあります。

  • 共有ロックと排他ロック
  • 意図ロック
  • レコードロック
  • ギャップロック
  • ネクストキーロック
  • 意図ロックを挿入する
  • 自動インクリメントロック

mysqlロックの詳細な説明

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

  • データの読み取り時には共有ロック (S ロック) が使用されます。
  • 排他ロック(eXclusive Locks、Xロックと表記)、データを変更するときにXロックを追加します

使用されるセマンティクスは次のとおりです。

  • 共有ロックは相互に排他的ではないため、次のように省略できます。読み取りと読み取りは並列に実行できます。
  • 排他ロックは他のロックと相互に排他的であり、書き込みと読み取り、書き込みと書き込みを並行して行うことはできないと省略できます。

データの書き込みタスクが完了しないと、他のタスクでデータを読み取ることができず、同時実行性に大きな影響を与えることがわかります。データベースに対応して、書き込みトランザクションがコミットされていない場合、関連データを読み取るための選択もブロックされることがわかります。ここでの選択はロック付きのものを指し、通常の選択では引き続きデータを読み取ることができます (スナップショット読み取り)。

2. 意図ロック

InnoDB では、複数の粒度ロックをサポートするためにインテンション ロックが導入され、行レベルのロックとテーブル レベルのロックが共存できるようになりました。意図ロックとは、将来のある時点でトランザクションが共有/排他ロックを追加する必要がある可能性があるため、事前に意図を宣言することを意味します。

1. インテンションロックはテーブルレベルのロック(テーブルレベルロック)です。

2. 意図ロックは次のように分類されます。

  • 意図的共有ロック (IS)。トランザクションがテーブル内の特定の行に共有 S ロックを追加する意図があることを示します。
  • 意図的排他ロック (IX)。トランザクションがテーブル内の特定の行に排他 X ロックを追加する意図があることを示します。

ロックの構文は次のとおりです。

共有モードで...ロックを選択します。ISロックを設定します。
更新するには...を選択します。IX ロックを設定します。

特定の行の S/X ロックを取得するには、トランザクションはまずテーブルに対応する IS/IX ロックを取得する必要があります。意図ロックは意図のみを示します。意図ロックは互いに互換性があります。互換性があり相互に排他的なテーブルは次のとおりです。


9 章
互換性がある互換性がある
9 章互換性がある互換性がある

インテンション ロックは互いに互換性がありますが、共有ロック/排他ロックとは相互に排他的です。互換性と相互排他性の表は次のとおりです。

バツ
互換性がある相互排除
9 章相互排除相互排除

専用ロックは非常に強力なロックであり、他のタイプのロックとは互換性がありません。これは実際には非常に簡単に理解できます。行を変更または削除する場合、データの一貫性を確保するために、この行での他の同時実行を禁止する強力なロックを取得する必要があります。

3. レコードロック

レコード ロック。インデックス レコードをブロックします。例: (id は pk です):

テーブル lock_example(id smallint(10),name varchar(20),主キー id) を作成します。engine=innodb;

データベース分離レベルは RR で、テーブルには次のデータが含まれています。

10、張三
20, リシ
30、王武

更新のために、id=1 の t から * を選択します。

実際、ここでは最初にテーブルの意図的な排他ロック (IX) を取得し、次にこのレコード行の排他ロックを取得して (インデックスが直接ここでヒットするためだと私は理解しています)、他のトランザクションが id=1 の行を挿入、更新、削除するのを防ぎます。

4. ギャップロック

ギャップ ロックは、インデックス レコード内のギャップ、最初のインデックス レコードの前の範囲、または最後のインデックス レコードの後の範囲をブロックします。上記の例、InnoDB、RR を引き続き使用します。

lock_example から * を選択
IDが8から15の間 
更新用;

この SQL ステートメントは、間隔 (8,15) をブロックして、他のトランザクションがこの間隔内の ID を持つレコードを挿入するのを防ぎます。

ギャップ ロックの主な目的は、他のトランザクションがその間隔内にデータを挿入して「繰り返し不可能な読み取り」が発生するのを防ぐことです。トランザクション分離レベルが Read Committed (RC) にダウングレードされると、ギャップ ロックは自動的に無効になります。

5. ネクストキーロック

一時キー ロックは、レコード ロックとギャップ ロックを組み合わせたものです。そのブロック範囲には、インデックス レコードとインデックス間隔の両方が含まれます。

デフォルトでは、InnoDB は次のキー ロックを使用してレコードをロックします。ただし、クエリされたインデックスに一意の属性が含まれている場合、Next-Key Lock は最適化され、Record Lock にダウングレードされます。つまり、範囲ではなくインデックス自体のみがロックされます。

たとえば、テーブル lock_example は上記と同じですが、id は通常のインデックス (キー) にダウングレードされます。つまり、ここでロックが宣言され (更新用)、インデックスがヒットしたとしても、インデックスには UK 制約がないため、InnoDB はネクストキー ロックとデータベース分離レベル RR を使用します。

トランザクション A は次のステートメントを実行しますが、コミットされません。

更新のために、id = 20 の lock_example から * を選択します。

トランザクション B が開始され、次のステートメントが実行され、ブロックされます。

lock_example に値 ('zhang'、15) を挿入します。

上記の例では、トランザクション A がクエリ ステートメントを実行した後、デフォルトで id=20 のレコードに次のキー ロックが追加されるため、トランザクション B は 10 (含む) から 30 (含まない) までのレコードを挿入するときにブロックされます。一時的なキーロックの主な目的は、ファントムリードを回避することです。トランザクション分離レベルが RC にダウングレードされると、一時的なキー ロックも無効になります。

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

既存のデータ行を変更したり削除したりするには、相互排他ロック (X ロック) を強化する必要があります。では、データ挿入の場合、相互排他を実現するために、このような強力なロックを追加する必要があるのでしょうか。意思ロックを挿入して出産します。

挿入意図ロックはギャップ ロックの一種であり (したがって、インデックスにも実装されています)、挿入操作専用です。複数のトランザクションが同じインデックスと範囲にレコードを挿入する場合、挿入位置が競合しない限り、トランザクションは互いにブロックされません。

挿入意図ロックは、同じインデックス ギャップに挿入する複数のトランザクションが、ギャップ内の同じ位置に挿入しない場合には、互いに待機する必要がないように、挿入の意図を通知します。

たとえば (テーブルはまだ lock_example で、データは上記と同じです)、トランザクション A が最初に実行され、レコード 10 と 20 に行が挿入されますが、まだコミットされていません。

t値(11, xxx)に挿入します。

トランザクション B は後で実行され、レコード 10 と 20 にも行を挿入します。

t値(12, ooo)に挿入します。

これは挿入操作であるため、挿入は同じ間隔で行われますが、挿入されたレコードは競合しないため、挿入意図ロックが使用されます。ここでは、トランザクション A はトランザクション B をブロックしません。

7. 自動インクリメントロック

自動インクリメント ロックは、AUTO_INCREMENT 列を挿入するトランザクションに特に使用される特別なテーブル レベルのロックです。最も単純なケースでは、1 つのトランザクションがテーブルにレコードを挿入している場合、最初のトランザクションによって挿入された行に連続した主キー値が含まれるように、他のすべてのトランザクションは待機する必要があります。

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

たとえば (テーブルは上記のように lock_example のままですが)、ID は AUTO_INCREMENT で、データベース テーブル内のデータは次のようになります。

1、張山
2、リシ
3、王武

トランザクション A が最初に実行されますが、まだコミットされていません: insert into t(name) values(xxx);

トランザクション B の後に実行: insert into t(name) values(ooo);

この時点で、トランザクション B の挿入操作は、トランザクション A がコミットされるまでブロックされます。

要約する

上記にまとめた 7 種類のロックは、次の 2 つの方法で区別できます。

1. ロックの相互排他性の程度に応じて、共有ロックと排他ロックに分けられます。

  • 共有ロック (S ロック、IS ロック) を使用すると、読み取りと読み取りの同時実行性が向上します。
  • 強力なデータ一貫性を確保するために、InnoDB は強力なミューテックス ロック (X ロック、IX ロック) を使用して、同じレコード行の変更と削除の連続性を保証します。

2. ロックの粒度に応じて、次のように分類できます。

  • テーブルロック:インテンションロック(IS ロック、IX ロック)、自己増分ロック。
  • 行ロック: レコードロック、ギャップロック、一時キーロック、挿入意図ロック。

  • InnoDB のきめ細かいロック (つまり行ロック) はインデックス レコードに実装されています (インデックスがヒットしない場合は失敗するというのが私の理解です)。
  • レコード ロックはインデックス レコードをロックします。ギャップ ロックは間隔をロックして、他のトランザクションが間隔に挿入されるのを防ぎます。一時キー ロックはインデックス レコード + 間隔をロックして、ファントム読み取りを防ぎます。
  • InnoDB は挿入の同時実行性を向上させるために挿入意図ロックを使用します。
  • ギャップ ロックと次のキー ロックは RR 以上のレベルでのみ有効であり、RC では機能しません。

さて、以上がこの記事の全内容です。この記事の内容が皆さんの勉強や仕事に一定の参考学習価値を持つことを願っています。ご質問があれば、メッセージを残してコミュニケーションしてください。123WORDPRESS.COM をご愛顧いただきありがとうございます。

以下もご興味があるかもしれません:
  • MySQL のロックの仕組みと使用法の分析
  • MySQL InnoDB のロック機構の詳細な説明
  • MySQLデータベースのロック機構の分析
  • MySQLの分離レベルとロックメカニズムの詳細な説明
  • MySQLのロック機構に関する最も包括的な説明

<<:  WeChatアプレットはキャンバスを使用して時計を描画します

>>:  Linuxのip netnsコマンドを使用してネットワークポートを分離し、IPアドレスを設定します。

推薦する

MySQL ビューの原理と使用法の詳細な分析

序文: MySQL では、ビューはおそらく最も一般的に使用されるデータベース オブジェクトの 1 つ...

MySQL データベースで UTF-8 エンコードを設定する方法

/etc/my.cnf または /etc/mysql/my.cnf ファイルを変更する [クライアン...

Vue で SuperMap を使用する練習

目次序文関連資料Vue プロジェクトが 2 次元ハイパーグラフを導入ハイパーグラフ 2D ケース引用...

scss で mixin が動作しない問題の解決方法 (ブラウザでコンパイルできない)

ミックスインメソッド: ブラウザはコンパイルできません: 以前のバージョンのsassでは上記の記述方...

JavaScript の Set データ構造の詳細な説明

目次1. セットとは何か2. セットコンストラクタ2.1) 配列2.2) 文字列2.3) 議論2.4...

Linux でファイルをあいまい検索するのに適したコマンドは何ですか?

1. はじめにこの記事では、主に Linux システムでコマンドライン ツールを使用してファイルを...

Linux で MySQL データベースのスケジュールされたバックアップを実装する簡単な方法

詳細な手順は次のとおりです。 1. ディスク容量を確認します。 [root@localhost バッ...

JSデータ型検出のさまざまな方法の概要

目次背景データ型を決定する方法は何ですか? 1. typeof を使用して基本データ型を決定します。...

MySQLカーソルの使い方と機能の詳細な説明

[mysqlカーソルの使い方と機能]例:現在、テーブル A、B、C の 3 つのテーブルがあります。...

CentOS で RPM を使用して MySQL 5.6 をインストールするチュートリアル

これまでのプロジェクトはすべて Windows システム環境にデプロイされていました。今回は Lin...

Dockerイメージの読み込み原理

目次Docker イメージ鏡とは何ですか? Dockerイメージの読み込み原理コミットミラーDock...

フォームで完全な選択または逆選択効果を実現する JavaScript

この記事では、フォームの完全選択または逆選択を実現するためのJavaScriptの具体的なコードを参...

Vue3ナビゲーションバーコンポーネントのカプセル化実装方法

参考までに、Vue3でナビゲーションバーコンポーネントをカプセル化し、スクロールバーのスクロールに合...

1 行または複数行のテキストがオーバーフローしたときに省略記号を表示する CSS を実装する方法

1. 単一行オーバーフロー1. 1 行がオーバーフローした場合、超過部分は表示されます...または、...

Linux のスクリーンコマンドとその使い方

画面紹介Screen は、コマンドライン端末切り替え用に GNU プロジェクトによって開発されたフリ...