MySQLのテーブル構造を変更する際に知っておきたいメタデータロックの詳しい解説

MySQLのテーブル構造を変更する際に知っておきたいメタデータロックの詳しい解説

序文

MySQL を扱ったことがある人なら、テーブル メタデータ ロックの待機についてよく知っているはずです。通常、これは変更操作中にブロックされ、プロセス リストを表示すると、スレッド ステータスがメタデータ ロックを待機中であることがわかります。この記事では、MySQL テーブル構造の変更に対するメタデータ ロックについて詳しく説明します。

DDL 操作をオンラインで実行する場合、発生する可能性のあるシステム負荷と比較して、最も懸念されるのは、MDL によって発生する可能性のあるブロッキング問題です。

MDL を取得できないために DDL 操作がブロックされると、テーブルに対する後続のすべての操作がブロックされます。典型的な例は次のとおりです。ブロックがしばらく続くと、Threads_running の急増と CPU アラームが発生します。

mysql> プロセスリストを表示します。
+----+-----------------+------------+-----------+-------+---------------------------------+------------------------------------+
| ID | ユーザー | ホスト | db | コマンド | 時間 | 状態 | 情報 |
+----+-----------------+------------+-----------+-------+---------------------------------+------------------------------------+
| 4 | event_scheduler | localhost | NULL | デーモン | 122 | 空のキューを待機中 | NULL |
| 9 | ルート | ローカルホスト | NULL | スリープ | 57 | | NULL |
| 12 | root | localhost | employees | クエリ | 40 | テーブル メタデータ ロックを待機中 | alter table slowtech.t1 add c1 int |
| 13 | root | localhost | employees | クエリ | 35 | テーブル メタデータ ロックを待機中 | select * from slowtech.t1 |
| 14 | root | localhost | employees | クエリ | 30 | テーブル メタデータ ロックを待機中 | select * from slowtech.t1 |
| 15 | root | localhost | employees | クエリ | 19 | テーブル メタデータ ロックを待機中 | select * from slowtech.t1 |
| 16 | root | localhost | employees | クエリ | 10 | テーブル メタデータ ロックを待機中 | select * from slowtech.t1 |
| 17 | root | localhost | employees | クエリ | 0 | 開始 | プロセスリストを表示 |
+----+-----------------+------------+-----------+-------+---------------------------------+------------------------------------+
セット内の行数 (0.00 秒)

それがオンラインで起こった場合、間違いなくビジネスに影響が及ぶでしょう。したがって、一般的には、業務のオフピーク時に DDL 操作を実行することが推奨されます。実際には、次の 2 つの考慮事項があります。1. システム負荷に大きな影響を及ぼさないようにする。 2. DDL がブロックされる可能性を減らします。

MDL導入の背景

MDL は MySQL 5.5.3 で導入され、主に 2 つの問題を解決するために使用されます。

RRトランザクション分離レベルにおける非反復読み取りの問題

以下に示すように、デモ環境では MySQL 5.5.0 を使用します。

セッション1> 開始;
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

セッション1> t1から*を選択します。
+------+------+
| ID | 名前 |
+------+------+
| 1 | へ |
| 2 | バ |
+------+------+
セット内の行数 (0.00 秒)

セッション2> テーブル t1 を変更し、c1 int を追加します。
クエリは正常、2 行が影響を受けました (0.02 秒)
記録: 2 重複: 0 警告: 0

セッション1> t1から*を選択します。
空のセット (0.00 秒)

セッション1>コミット;
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

セッション1> t1から*を選択します。
+------+------+------+
| ID | 名前 | c1 |
+------+------+------+
| 1 | a | NULL |
| 2 | b | NULL |
+------+------+------+
セット内の行数 (0.00 秒)

RR 分離レベルであるにもかかわらず、トランザクションがオンになっていると 2 番目のクエリには結果がないことがわかります。

マスタースレーブレプリケーションの問題

マスターとスレーブのデータ間の不整合、マスタースレーブレプリケーションの中断などが含まれます。

たとえば、マスターとスレーブのデータは以下のように矛盾しています。

セッション1> テーブル t1(id int,name varchar(10)) を作成します。エンジンは innodb です。
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

セッション1> 開始;
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

session1> t1に値(1,'a')を挿入します。
クエリは正常、1 行が影響を受けました (0.00 秒)

セッション2> テーブル t1 を切り捨てます。
クエリは正常、影響を受けた行は 0 行 (0.46 秒)

セッション1>コミット;
クエリは正常、影響を受けた行は 0 行 (0.35 秒)

セッション1> t1から*を選択します。
空のセット (0.00 秒)

ライブラリの結果を見てみましょう

session1> slowtech.t1 から * を選択します。
+------+------+------+
| ID | 名前 | c1 |
+------+------+------+
| 1 | a | NULL |
+------+------+------+
セット内の行数 (0.00 秒)

binlog の内容を見ると、切り捨て操作が最初に記録され、挿入操作が後で記録されていることがわかります。

# 7140 で
#180714 19:32:14 サーバー ID 1 end_log_pos 7261 クエリ thread_id=31 exec_time=0 error_code=0
タイムスタンプを 1531567934/*!*/ に設定します。
テーブル t1(id int,name varchar(10)) を作成 engine=innodb
//*!*/;

# 7261 で
#180714 19:32:30 サーバー ID 1 end_log_pos 7333 クエリ thread_id=32 exec_time=0 error_code=0
タイムスタンプを 1531567950/*!*/ に設定します。
始める
//*!*/;
# 7333で
#180714 19:32:30 サーバー ID 1 end_log_pos 7417 クエリ thread_id=32 exec_time=0 error_code=0
タイムスタンプを 1531567950/*!*/ に設定します。
テーブルt1を切り捨てる
//*!*/;
# 7417 で
#180714 19:32:30 サーバー ID 1 end_log_pos 7444 Xid = 422
専念 /*!*/;

# 7444 で
#180714 19:32:34 サーバー ID 1 end_log_pos 7516 クエリ thread_id=31 exec_time=0 error_code=0
タイムスタンプを 1531567954/*!*/ に設定します。
始める
//*!*/;
# 7516 で
#180714 19:32:24 サーバー ID 1 end_log_pos 7611 クエリ thread_id=31 exec_time=0 error_code=0
タイムスタンプを 1531567944/*!*/ に設定します。
t1 に値(1,'a') を挿入する
//*!*/;
# 7611 で
#180714 19:32:34 サーバー ID 1 end_log_pos 7638 Xid = 421
専念 /*!*/;

セッション 2 がテーブル削除操作を実行すると、マスターとスレーブの関係が中断されます。

興味深いことに、セッション 2 がテーブル変更操作を実行すると、操作は依然としてブロックされ、ブロック時間は innodb_lock_wait_timeout パラメータによって制限されます。

mysql> プロセスリストを表示します。
+----+-------+-----------+----------+--------+-------+-------------------+----------------------------+
| ID | ユーザー | ホスト | db | コマンド | 時間 | 状態 | 情報 |
+----+-------+-----------+----------+--------+-------+-------------------+----------------------------+
| 54 | root | localhost | NULL | クエリ | 0 | NULL | プロセスリストを表示 |
| 58 | ルート | ローカルホスト | slowtech | スリープ | 1062 | | NULL |
| 60 | root | localhost | slowtech | クエリ | 11 | tmp テーブルにコピー | alter table t1 add c1 int |
+----+-------+-----------+----------+--------+-------+-------------------+----------------------------+
セット内の行数 (0.00 秒)

MDLの基本概念

まずは公式声明を見てみましょう。

トランザクションのシリアル化可能性を保証するために、サーバーは、あるセッションが、別のセッションで明示的または暗黙的に開始された未完了のトランザクションで使用されるテーブルに対してデータ定義言語 (DDL) ステートメントを実行することを許可してはなりません。

サーバーは、トランザクション内で使用されるテーブルに対してメタデータ ロックを取得し、トランザクションが終了するまでそれらのロックの解放を延期することでこれを実現します。

テーブルのメタデータ ロックにより、テーブルの構造の変更が防止されます。

このロック アプローチでは、1 つのセッション内のトランザクションによって使用されているテーブルは、トランザクションが終了するまで他のセッションの DDL ステートメントで使用できません。

上記の説明から、

1. MDL の本来の目的は、トランザクション内のテーブルの構造が変更されないように保護することです。

2. ここで言及するトランザクションには、明示的なトランザクションと AC-NL-RO (自動コミット非ロック読み取り専用) トランザクションの 2 種類が含まれます。明示的なトランザクションには、1. AutoCommit がオフになっている操作と、2. begin または start transaction で開始された操作の 2 種類があります。 AC-NL-RO は、AutoCommit がオンになっている選択操作として理解できます。

3. MDL はトランザクション レベルであり、トランザクションが終了した後にのみ解放されます。これに先立って、実際に同様の保護メカニズムが存在しましたが、それはステートメント レベルのものでした。

MDL はテーブルだけでなく、次の表に示すように他のオブジェクトにも適用できることに注意してください。ここで、「待機状態」は「show processlist」の状態に対応します。

データベースの同時実行性を向上させるために、MDL は 11 種類に分かれています。

  • MDL_INTENTION_EXCLUSIVE
  • MDL_SHARED
  • MDL_SHARED_HIGH_PRIO
  • MDL_SHARED_READ
  • MDL_SHARED_WRITE
  • MDL_SHARED_WRITE_LOW_PRIO
  • MDL_SHARED_アップグレード可能
  • MDL_SHARED_READ_ONLY
  • MDL_SHARED_NO_WRITE
  • MDL_SHARED_NO_READ_WRITE
  • MDL_排他的

よく使用されるものは MDL_SHARED_READ、MDL_SHARED_WRITE、MDL_EXCLUSIVE で、それぞれ SELECT 操作、DML 操作、DDL 操作に使用されます。その他の対応する操作については、ソース コード sql/mdl.h を参照してください。

MDL_EXCLUSIVEの公式説明は、

/*
排他的なメタデータ ロック。
このロックを保持している接続は、テーブルのメタデータとデータの両方を変更できます。
このロックが保持されている間は、他のタイプのメタデータ ロックを許可することはできません。
CREATE/DROP/RENAME TABLE文および実行に使用します。
他の DDL ステートメントの特定のフェーズ。
*/

つまり、MDL_EXCLUSIVE は排他ロックです。保持期間中は、SELECT や DML 操作など、他の種類の MDL を許可することはできません。

このため、DDL 操作がブロックされると、後続の他の操作もブロックされます。

MDLに関する補足情報

1. MDL の最大待機時間は lock_wait_timeout パラメータによって決定され、デフォルト値は 31536000 (365 日) です。ツールを使用して DDL 操作を実行する場合、この値は適切ではありません。実際、pt-online-schema-change と gh-ost は対応する調整を行っており、前者は 60 秒、後者は 3 秒かかります。

2. SQL 文が構文的に有効であっても、実行中に列名が存在しないなどのエラーが発生した場合は、MDL ロックも取得され、トランザクションが終了するまで解放されません。

要約する

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

以下もご興味があるかもしれません:
  • MySQL でテーブル メタデータ ロックを待機する理由と方法
  • MYSQL メタデータ ロック (MDL ロック) MDL ロックの問題分析
  • MySQLスレーブは列の外部キーチェックと自動増分ロックを遅延します
  • MySQLのネクストキーロックのロック範囲についての簡単な説明
  • MySQL ロック制御同時実行方法
  • PHP+MySQL の高同時ロックトランザクション処理問題の解決方法
  • MYSQL メタデータ ロック (MDL ロック) の理論とロック タイプ テスト

<<:  Vue における v-for のキーの一意性の詳細な説明

>>:  Nginx http ヘルスチェック構成プロセス分析

推薦する

CSS3は遷移を高速化し、遅延させる

1. 速度制御機能を使用して、トランジション効果(加速、減速など)の速度曲線を制御します。速度制御機...

反応ルーティングでパラメータを渡すいくつかの方法についての簡単な説明

最初のパラメータ渡し方法は、動的ルーティングパラメータ渡しです。リンクのパス属性を設定することで、ル...

HTML でよく使われるタグの概要 (必読)

コンテンツ詳細タグ: <h1>~<h6>タイトルタグ<pre>テ...

仮想マシンのLinux初心者がIPを設定し、ネットワークを再起動する

仮想マシンを初めて使用する方や、仮想マシンに Linux をインストールしたばかりの方は、システムが...

IDEA で Linux コマンドを使用する方法

Windows システムと比較して、Linux システムは多数の豊富なコマンドライン ツールを提供し...

閲覧時に作成されたWebページの下部にある余分な空白スペースを削除する方法

Dreamweaver または FrontPage を使用して HTML Web ページを作成する場...

MySQLエラー10061を解決する方法

この記事では、「'localhost' (10061) の MySQL サーバーに接...

MySQL コピーテーブルと許可分析の 3 つの実装方法

テーブルを素早くコピーする方法まず、テーブル db1.t を作成し、1000 行のデータを挿入します...

IE9 のネイティブ ページ互換性の問題に対する解決策についての簡単な説明

序文最近、クライアントのネイティブページを引き継ぎました。顧客は、ページが IE9 以降のバージョン...

Dockerでローカルマシン(ホストマシン)にアクセスする方法

質問Docker でローカル データベースにアクセスするにはどうすればよいでしょうか? 127.0....

MySQLのビューとインデックスの使い方と違いの詳細な説明

MySQL ビュー簡単に言えば、MySQL ビューは SELECT コマンドを定義するためのショート...

ゲーム着物メモ問題の簡単な分析

本日、ゲームを再起動した後、バックアップしたデータをターゲットデータベースにインポートできないことが...

JSはじゃんけんゲームを実装します

この記事の例では、じゃんけんゲームを実装するためのJSの具体的なコードを参考までに共有しています。具...

HTMLセマンティクスと関連するフロントエンドフレームワークの詳細な分析

セマンティクスについて意味論は、記号やシンボルとそれらが表す意味との関係を研究する学問です。言語学で...

nginxのデフォルトポートを変更する方法の詳細な説明

まず設定ファイルがどこにあるか調べる nginx.confはどこにありますかこれらのディレクトリを調...