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アドレスを設定します。

推薦する

Linux での一般的なシェル スクリプト コマンドと関連知識

目次1. 覚えておくべき知識1. 変数タイプ2. シェル変数の説明3. シングルクォート、ダブルクォ...

Mac VMware Fusion CentOS7 静的 IP 構成チュートリアル図

目次CentOS7をインストールする静的IPの設定viを使用してファイルを編集するCentOS7をイ...

JavaScript配列をツリー構造に変換する方法

1. 需要バックエンドは、フロントエンドがツリー構造(重複データなし)に変換するためのデータを提供し...

MySQL 8.0.12 クイックインストールチュートリアル

MySQL 8.0.12 のインストールには 2 日かかり、さまざまな問題が発生しました。以下にまと...

JavaScriptはオブジェクトの不要なプロパティを削除します

目次例方法1: 削除方法2: 分解補充する要約するThinking シリーズは、10 分で実用的なプ...

Linux のような環境で jdk1.8 をインストールし、環境変数を設定する方法の詳細な説明

設定は非常にシンプルですが、毎回確認しないといけないので、記録だけ残しておきます。 1. インストー...

JavaScriptはクリックトグル機能を実装します

この記事の例では、クリックして切り替える機能を実装するためのJavaScriptの具体的なコードを参...

面接では、select...for update がテーブルをロックするのか、それとも行をロックするのか尋ねられました。

目次確認する:例の検証と組み合わせるselect クエリ ステートメントはロックされませんが、sel...

MYSQL8.0.13 無料インストール版 設定チュートリアル例 詳細説明

1. ダウンロード、例として8.0を取り上げますダウンロードアドレス: https://dev.my...

CSSはフロントエンドの画像変形の問題を完璧に解決します

Toutiao IT School で、CSS がフロントエンドの画像変形の問題を完璧に解決するとい...

HTML内の画像はbase64でエンコードされた文字列に直接置き換えられます

最近、画像はあるのに外部画像リソースが参照されていないウェブページを見つけました。気になりました。コ...

WeChatミニプログラムマップの使い方を詳しく解説

この記事の例では、WeChatアプレットマップで使用される具体的な実装コードを参考までに共有していま...

Docker に Zookeeper を素早くインストールする方法の詳細なチュートリアル

Docker で Zookeeper を素早くインストール会社を変わってから長らくZookeeper...

MacOS で Docker を使用して MySQL マスター スレーブ データベースを作成する方法

1. MySQLイメージを取得するターミナルから最新のMySQLイメージを取得するdocker pu...

MySQL SQL ステートメントが遅い場合の一般的な原因と解決策

1. インデックス不足または無効なインデックスによるクエリの遅延数千万件のデータを含むテーブルで、イ...