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

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

前面に書かれた

データベースは本質的に共有リソースであるため、同時アクセスのパフォーマンスを最大化する一方で、各ユーザーが一貫した方法でデータを読み取り、変更できることを保証する必要があります。ロックはこの種の問題を解決する最善の手段です。

まず、id を主キー、name をセカンダリ インデックス、address を一意のインデックスとして、新しいテーブル test を作成します。

テーブル「test」を作成します(
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` int(11) NOT NULL,
 `アドレス` int(11) NOT NULL,
 主キー (`id`)、
 ユニークキー `idex_unique` (`address`)、
 キー `idx_index` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=7 デフォルト CHARSET=utf8mb4;

INSERTメソッドの行ロック

2 つのトランザクションが同じ主キーを持つ行レコードに対して INSERT 操作を連続して実行する場合、トランザクション A が最初に行ロックを取得するため、トランザクション B はトランザクション A がコミットされた後に行ロックが解除されるまでしか待機できないことがわかります。同様に、一意のインデックス フィールド アドレスにデータを挿入する場合も、行ロックを取得する必要があります。図は主キーの挿入プロセスに似ているため、ここでは繰り返しません。

ただし、両方のトランザクションが補助インデックス フィールド名にデータを挿入する場合は、補助インデックス フィールドの値が同じであっても、データベース内で異なる行が操作され、競合が発生しないため、ロックが取得されるのを待つ必要はありません。

Update メソッドは Insert メソッドと同様の結果をもたらします。

SELECT FOR UPDATE でのテーブルロックと行ロック

トランザクション A の SELECT FOR UPDATE ステートメントは、テーブル test のテーブル ロックを取得します。このとき、トランザクション B は挿入操作の実行時にブロックされます。トランザクション A がコミットしてテーブル ロックを解除した後でのみ、トランザクション B は対応する行ロックを取得し、挿入操作を実行できます。

ただし、トランザクション A の SELECT FOR UPDATE ステートメントの後に WHERE id = 1 が続く場合、このステートメントは行ロックのみを取得し、テーブル ロックは取得しないため、トランザクション B の他の主キーに対する変更操作はブロックされません。

セカンダリインデックスのギャップロック

まず、テスト テーブルの下のデータを見てみましょう。

mysql> テストから * を選択します。
+----+------+---------+
| ID | 名前 | 住所 |
+----+------+---------+
| 3 | 1 | 3 |
| 6 | 1 | 2 |
| 7 | 2 | 4 |
| 8 | 10 | 5 |
+----+------+---------+
セット内の 4 行 (0.00 秒)

ギャップ ロックは行ロックの一種と言えます。違いは、範囲内のレコードをロックすることです。その機能は、ファントム リード、つまり間隔データ エントリの突然の増加または減少を回避することです。主な解決策は次のとおりです。

  • ギャップに新しいデータが挿入されるのを防ぐため、ギャップ ロックと呼ばれます。
  • 更新操作後に既存のデータがギャップ内のデータにならないようにします (たとえば、id = 7 の name フィールドが 1 に更新されると、name = 1 のエントリの数は 2 から 3 に変わります)

InnoDB がギャップ ロックを自動的に使用するための条件は次のとおりです。

  • MySQLのデフォルトの動作レベルであるRepeatable Read分離レベル
  • 検索条件にはインデックスが必要です (インデックスがない場合、テーブル全体のスキャンが実行され、テーブル全体のすべてのレコードがロックされます)

InnoDB は、インデックス レコードをスキャンするときに、最初に選択したインデックス行レコードに行ロックを追加し、次にインデックス レコードの両側のギャップにギャップ ロックを追加します (指定されたパラメータより小さい最初の値を見つけるために左にスキャンし、指定されたパラメータより大きい最初の値を見つけるために右にスキャンして、間隔を構築します)。ギャップがトランザクション A によってロックされている場合、トランザクション B はこのギャップにレコードを挿入できません。

ここで言及している「ギャップ ロック」は、実際には GAP LOCK ではなく、RECORD LOCK + GAP LOCK であり、InnoDB では NEXT_KEY LOCK と呼ばれています。

例を見てみましょう。テーブルを作成するときに、補助インデックスとして名前列を指定します。現在、この列の値は[1,2,10]です。ギャップの範囲は (-∞, 1], [1,1], [1,2], [2,10], [10, +∞) です。

ラウンド1:

  • トランザクション A SELECT ... WHERE name = 1 FOR UPDATE;
  • (-∞, 2)にギャップロックを追加
  • トランザクションB INSERT ... name = 1 ブロック
  • トランザクション B INSERT ... name = -100 がブロックされました
  • トランザクションB INSERT ... name = 2 が成功
  • トランザクションB INSERT ... name = 3 が成功

第2ラウンド:

  • トランザクション A SELECT ... WHERE name = 2 FOR UPDATE;
  • [1, 10)にギャップロックを追加
  • トランザクションB INSERT ... name = 1 ブロック
  • トランザクション B INSERT ... name = 9 ブロック
  • トランザクション B INSERT ... name = 10 成功
  • トランザクション B INSERT ... name = 0 成功

第3ラウンド:

  • トランザクション A SELECT ... WHERE name <= 2 FOR UPDATE;
  • (-∞、+∞) のギャップロックを追加
  • トランザクション B INSERT ... name = 3 ブロック
  • トランザクション B INSERT ... name = 300 がブロックされました
  • トランザクション B INSERT ... name = -300 がブロックされました

InnoDB ロックメカニズムの概要

参考文献

  • 「MySQL テクニカル インサイダー InnoDB ストレージ エンジン」第 2 版 (Jiang Chengyao 著)
  • MySQL InnoDBのロックについて

要約する

以上がこの記事の全内容です。この記事の内容が皆様の勉強や仕事に何らかの参考学習価値をもたらすことを願います。123WORDPRESS.COM をご愛顧いただき、誠にありがとうございます。

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

<<:  Websocket に基づくシンプルなチャットルームダイアログの実装

>>:  CentOS 8 カスタム ディレクトリ インストール nginx (チュートリアルの詳細)

推薦する

クラウド サーバー Ubuntu_Server_16.04.1 に MySQL をインストールしてリモート接続を有効にする方法

1. MySQLをインストールします。対応するソフトウェアをインストールするには、次の 3 つのコマ...

JavaScriptはクリックするとランダムなグラフィックを生成します

この記事では、クリックするとランダムグラフィックの生成を実現するJavaScriptの具体的なコード...

MySQLパーティションテーブルの詳細な説明

序文:パーティショニングはテーブル設計パターンです。一般的に、テーブル パーティショニングとは、条件...

Ubuntu 18.04 に VMware Tools をインストールする際のエラーを解決する

1. オンライン チュートリアルによると、Ubuntu 18.04 のインストールはまだ失敗します。...

CSSを使用してTDのINPUTの幅を設定する

最近、C# を使用して Web プログラムを作成していたときに、次のような問題が発生しました。 Te...

mysql 5.7.18 winx64 無料インストール設定方法

1. ダウンロード2. 減圧3. パス環境変数を追加し、mysqlが配置されているbinディレクトリ...

SSMプロジェクトは、ホットデプロイメント構成を実装するためにTomcatとMavenを使用してWARパッケージとしてデプロイされることが多い。

背景ご存知のとおり、JavaEE プロジェクトを開発した後は、そのプロジェクトをサーバーの Tomc...

docker に基づいて nginxssl 設定を開始する

前提条件クラウドサーバー(Alibaba Cloud、Tencent CloudなどのcentOS)...

mysql5.7のインストールとNavicateの長期無料利用の実施手順

(I) mysql5.7のインストール: ❀詳細:無料のグリーンバージョン5.7のインストール方法は...

Linux で MySQL 8.0 バージョンをアンインストールする方法

1. MySQLをシャットダウンする [root@localhost /]# サービスmysqldを...

ディスク容量不足による MySQL レプリケーション障害の解決方法

目次ケースシナリオ問題を解決するまとめケースシナリオ本日、オンラインで問題が発見されました。監視範囲...

WindowsにOpenSSHをインストールし、SSHキーを生成してLinuxサーバーにログインします。

SSH の正式名称は Secure SHell です。 SSH を使用すると、送信されるすべてのデ...

Vue2とVue3の兄弟コンポーネント通信バスの違いと使い方

目次vue2.x vue3.x tiny-emitterプラグインの使用Mittプラグインの使用vu...

JavaScript マクロタスクとマイクロタスクの実行順序についての簡単な説明

目次1. JavaScriptはシングルスレッドです1. 同期タスク2. 非同期タスク2. タスクキ...

MYSQL トランザクション チュートリアル Yii2.0 マーチャント引き出し機能

序文私はプログラマーとしてスタートした PHP プログラマーです。これまで、トレーニング コースで勉...