MySQLのロックについて理解しておくべきこと

MySQLのロックについて理解しておくべきこと

1. はじめに

MySQL ロックは、その範囲に応じて、グローバル ロック、テーブル ロック、行ロックに分けられます。行ロックはデータベース エンジンによって実装されます。すべてのエンジンが行ロックを提供しているわけではありません。MyISAM は行ロックをサポートしていないため、この記事では InnoDB エンジンを例に行ロックを紹介します。

2. グローバルロック

MySQL は、データベース インスタンス全体をロックするグローバル ロックを提供します。

文法:

読み取りロック付きテーブルのフラッシュ

このステートメントは、通常、バックアップに使用されます。このステートメントを実行すると、データベース内の開いているテーブルがすべて閉じられ、データベース内のすべてのテーブルがグローバル読み取りロックでロックされます。同時に、他のスレッドの更新ステートメント (追加、削除、変更)、データ定義ステートメント (テーブルの作成、テーブル構造の変更)、および更新トランザクションの送信がブロックされます。

MySQL 8.0 以降では、MySQL はバックアップにバックアップ ロックを直接使用できます。

声明:

バックアップのためにインスタンスをロックするインスタンスのロックを解除する

このロックの範囲は広く、 REPAIR TABLE TRUNCATE TABLE, OPTIMIZE TABLE操作やアカウント管理など、ファイルの作成、名前変更、削除を防止します。もちろん、これらの操作はメモリ一時テーブルに対して実行できます。メモリ テーブルにはなぜこれらの制限が適用されないのでしょうか?メモリテーブルはバックアップする必要がないため、これらの条件を満たす必要はありません。

3. テーブルロック

Mysql のテーブル レベル ロックは、メタデータ ロック (MDL) とテーブル ロックの 2 つのカテゴリに分けられます。

メタデータ ロック (MDL) は明示的に使用する必要はなく、テーブルにアクセスすると自動的に取得されます。この機能をサポートするには、MySQL バージョン 5.5 以上が必要です。テーブルを追加、削除、変更、またはチェックすると、テーブルに MDL 読み取りロックが追加されます。テーブル構造が変更されると、MDL 書き込みロックが追加されます。 MDL ロックにはいくつかのルールがあります:

読み取りロックは相互に排他的ではないため、複数のスレッドが同じテーブルを追加、削除、変更、および照会できます。読み取り/書き込みロックと書き込みロックは相互に排他的です。テーブル構造の変更のセキュリティを確保するために、複数のスレッドが同じテーブルにフィールドを追加するなどのテーブル構造操作を実行する必要がある場合は、シリアル化され、ロック待機が必要になります。 MDL の書き込みロック優先度は MDL の読み取りロック優先度よりも高くなりますが、max_write_lock_count システム変数を設定することでこの状況を変更できます。書き込みロック要求がこの変数で設定された数を超えると、MDL 読み取りロック優先度は MDL 書き込みロック優先度よりも高くなります。 (デフォルトではこの数値は大きいため、書き込みロックの優先度が下がることを心配する必要はありません。) MDL ロックは、トランザクションが終了した後にのみ解除する必要があります。

したがって、データベース テーブル構造を操作するときは、長いトランザクションを使用しないように注意する必要があります。これは具体的に何を意味するのでしょうか。例を挙げてみましょう:

上の図は、4 つのセッションによるステートメントの実行を示しています。まず、SessionA はトランザクションを開始しますが、コミットしません。次に、SessionB はクエリを実行します。これらは MDL 読み取りロックを取得するため、互いに影響を及ぼさず、正常に実行できます。SessionC はフィールドを追加します。MDL の書き込みと読み取りは相互に排他的であるため、SessionC はブロックされます。次に、SessionD がクエリ ステートメントの実行を開始します。SessionC がブロックされているため、SessionD もブロックされます。したがって、シミュレートした SessionA のトランザクションは長いトランザクションであり、その後テーブル構造が変更され、テーブルに対する後続のすべての読み取りおよび書き込み操作が実行不可能になります。したがって、実際のシナリオでは、ビジネス リクエストが頻繁に発生する場合、テーブル構造の変更によってライブラリのスレッドがブロックされる可能性があります。

テーブル ロックの構文は次のとおりです。

LOCK TABLES tbl_name [[AS] alias] lock_type [, tbl_name [[AS] alias] lock_type] ... lock_type: { READ [LOCAL] | [LOW_PRIORITY] WRITE} UNLOCK TABLES

テーブル ロックは、読み取りロックと書き込みロックに分けられます。読み取りロックは相互に排他的ではありませんが、読み取りロックを取得した後はデータを書き込むことはできません。読み取りロックを取得していない他のセッションでもテーブルを読み取ることができるため、読み取りロックの目的はテーブルへの書き込みを制限することです。テーブルが読み取りロックによってロックされている場合、挿入ステートメントを実行するとエラーが報告されます。エラーは次のとおりです。

1099 - テーブル 'XXXX' は読み取りロックでロックされており、更新できません

書き込みロックが取得されると、テーブルは読み取りおよび書き込み可能になります。書き込みロックは相互に排他的です。セッションがテーブルの書き込みロックを取得すると、書き込みロックが解除されるまで他のセッションはテーブルにアクセスできません。

テーブルのロックは、 unlock tablesを使用して解除することも、クライアント ポートによって自動的にロック解除することもできます。テーブルのlock tablesテーブルを排他的にロックします。これにより、他のスレッドによるテーブルの読み取りと書き込みが制限されるだけでなく、このスレッドの次の操作オブジェクトも制限されます。

4. 行ロック(InnoDB)

MySQL の行ロックはエンジン レベルで実装されているため、ここでは InnoDB エンジンでの行ロックについて説明します。以下では、InnoDB での一般的な行ロックをいくつか詳しく紹介します。

4.1 共有ロック

共有ロックを使用すると、トランザクションはロックを取得した後に読み取り操作を実行できます。共有ロックは相互に排他的ではありません。1 つのトランザクションが共有ロックを取得した後、別のトランザクションも共有ロックを取得できます。共有ロックを取得した後は書き込み操作は実行できません。

4.2 排他ロック

排他ロックを使用すると、トランザクションはロックを取得した後、行を更新または削除できます。名前が示すように、排他ロックは相互に排他的です。トランザクションが排他ロックを取得した後、ロックが解除されるまで他のトランザクションは排他ロックを取得できません。

4.3 意図ロック

InnoDB は複数の粒度のロックをサポートしており、行ロックとテーブルロックが共存できます。ここで言及したインテンション ロックは実際にはテーブル レベルのロックですが、単独では存在しないため行ロックに入れました。その出現には必ず行ロック (共有ロックまたは排他ロック) が伴います。その主な目的は、テーブル内の行がロックされるか、ロックされていることを示すことです。

インテンション ロックは、行ロックとの組み合わせに応じて次のタイプに分類できます。

  • 意図的な排他ロック: テーブル内の特定の行に対して排他ロックが取得されることを示します。
  • 意図的な共有ロック: テーブル内の特定の行に対して共有ロックが取得されることを示します。

意図ロックの取得は行ロックの取得の前に行う必要があります。つまり、共有ロックの前に共有意図ロックを取得する必要があり、排他ロックについても同様です。

では、この意図ロックは具体的に何をするのでしょうか?

これを説明する前に、インテンション ロックと行ロックの互換性関係を見てみましょう。

--- 排他ロック(X) 意図的な排他ロック(IX) 共有ロック(S) 意図共有ロック (IS)
排他ロック(X) 対立対立対立対立
意図的な排他ロック(IX) 対立互換性がある対立互換性がある
共有ロック(S) 対立対立互換性がある互換性がある
意図共有ロック (IS) 対立互換性がある互換性がある互換性がある

トランザクション A と B の 2 つのトランザクションがあると仮定します。トランザクションは共有ロックを取得し、テーブル内の行をロックします。この行は読み取りのみ可能で、書き込みはできません。ここで、トランザクション B はテーブル全体の書き込みロックを申請します。トランザクション B が正常に適用された場合、テーブル内のすべての行に確実に書き込むことができるため、A によって取得された行ロックと確実に競合します。このような競合を回避するために、データベースは競合検出を実行します。では、どのように検出するのでしょうか?方法は2つあります:

テーブルがテーブル レベルのロックを持つ他のトランザクションによってロックされているかどうかを判断します。テーブル内の各行が行ロックによってロックされているかどうかを判断します。

テーブルの各行を決定するには、すべてのレコードをトラバースする必要があり、非効率的です。そのため、データベースは最初の方法、つまり意図ロックを使用して競合を検出します。

要約する

この記事では、主にMySQLのロックスコープの観点からMySQLのロックを分析します。MySQLは、ロックスコープに応じて、グローバルロック、テーブルロック、行ロックに分けられます。グローバル ロックとテーブル ロックは MySQL 自体によって実装され、行ロックはエンジン レベルで実装されます。 InnoDB の行ロックは、主に共有ロックと排他ロックに分けられます。共有ロックが要求されると、行は読み取り専用になり、共有ロックは相互に排他的ではなくなります。排他ロックが取得されると、行を更新および削除できます。排他ロックは他のロックと相互に排他的です。最後に、行ロックに基づく意図的ロックについて説明しました。意図的ロックは主に、ロック競合検出の効率を向上させるために、行がロックされているか、ロックされようとしていることを意味します。もちろん、InnoDB にはギャップ ロック、レコード ロック、Next-Key ロックなど、他のロックもあります。これらはこの記事の範囲外です。興味があれば、自分で勉強してください。

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • MySQL デッドロック シナリオ例の分析
  • MySQL InnoDB のロック機構の詳細な説明
  • 魔法のMySQLデッドロックトラブルシューティング記録
  • MySQL における楽観的ロックと悲観的ロックの例
  • Mysqlは実行中のトランザクションを照会し、ロックを待機する方法

<<:  Linux システムで .sh ファイルを実行する方法

>>:  Vue エクスポート Excel 機能の全プロセス記録

推薦する

Pycharmとsshリモートアクセスサーバーdockerの詳細なチュートリアル

背景: 一部の実験はサーバー上で完了する必要があります。したがって、リモート サーバー上のコードをロ...

MySQL 文字列連結と null 値の設定のためのインスタンス メソッド

#文字列連結 concat(s1,s2); テーブル内の last_name と first_nam...

レスポンシブ原則のソースコード分析のVue解釈

目次初期化初期化状態()初期化プロパティ()初期化データ()観察する()オブザーバーリアクティブを定...

CSS3 を使用して円形スクロール プログレス バー アニメーションを作成する例

テーマ今日は、CSS3 を使用して円形スクロール プログレス バー アニメーションを作成する方法を説...

Tomcat のメモリ構成の正しい姿勢についての簡単な説明

1. 背景多くのブログや記事を読みましたが、JVM のメモリ割り当て方法に関する包括的な記事は見つか...

Vue は URL に基づいて非同一オリジンのファイルをどのようにダウンロードするのか

一般的に、URL に基づいてファイルをダウンロードする場合、次の 2 つの解決策があります。 1. ...

MySQL デッドロック シナリオ例の分析

序文最近、MySQL で RR レベルでデッドロック問題に遭遇しました。興味深いと思ったので、調べて...

Vueのコンポーネント値の転送から始まるオブザーバーモードの詳細な説明

目次オブザーバーパターンVue パス値最初のステップは、main.jsにバスを登録することです。 2...

JavaScript 関数型プログラミングの基礎

目次1. はじめに2. 関数型プログラミングとは何ですか? 3. 純粋関数(関数型プログラミングの基...

XHTMLはHTMLのいくつかの廃止された要素を使用しなくなりました

CSS ウェブページレイアウトを行う場合、XHTML1.0 仕様に準拠する必要があることは誰もが知っ...

JS 面接の質問: forEach はループから抜け出すことができますか?

この質問をされたとき、私は無知で頭が真っ白になりました。もちろん、正しく答えられませんでした。私はず...

MySQL データベースのインデックス順序の詳細な説明

目次事件の原因解剖学ファイルの並べ替えファイルのソートが非常に遅いのですが、他に解決策はありますか?...

CentOS7 に YUM 経由で MySQL 5.7 をインストールする詳細な手順

1. インストールパッケージを保存する場所に移動しますcd /home/lnmp 2. MySQL ...

Linux ncコマンドの概要

NC のフルネームは Netcat (Network Knife) で、作成者は Hobbit &a...

Vue で配列パラメータを渡すための get / delete メソッド

フロントエンドとバックエンドがやり取りする場合、get または delete を介してバックエンドに...