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 ヘルスチェック構成プロセス分析

推薦する

SpringBoot でマイクロサービスを構築するために Docker を使用した実際の記録を分析する

それは何ですか? Spring Boot は、Spring オープンソース組織のサブプロジェクトであ...

VirtualBox を使用して Linux クラスターをシミュレートする方法

1. ホストMacbookにHOSTをセットアップする前回のドキュメントでは仮想マシンの静的 IP ...

Oracle の開閉の 4 つのモード

>1 データベースを起動するcmd コマンド ウィンドウで、「sqlplus」を直接入力して ...

CentOS7.4 で JDK1.8 をインストールするためのグラフィカル チュートリアル

Linux インストール JDK1.8 手順1. CentOS に独自の openJDK があるかど...

Docker は 2003 年の問題を解決するために MySQL リモート接続を導入しました

MySQLへの接続ここでは、リモート接続に navicat を使用します。MySQL に接続する前に...

MySQL sql_mode の変更が有効にならない理由と解決策

目次序文シナリオシミュレーション要約する序文最近、sql_mode の話題については何度も話し合われ...

パーティクルダイナミックボタン効果を実現するCSS

オリジナルリンクhttps://github.com/XboxYan/no…ボタンは、おそらく We...

ウェブデザインにおけるポップアップウィンドウとフローティングレイヤーのデザイン

従来のソフトウェアから Web ウェアへの段階的な移行の傾向の中で、デザイン パターンとテクノロジは...

現在のマウススライドの座標を取得するVue+openlayer5メソッド

序文: Vue プロジェクトで現在のマウスの座標を取得するにはどうすればよいでしょうか。ここで共有す...

MySql ファジークエリ JSON キーワード取得ソリューションの例

目次序文オプション1:オプション2:オプション3:オプション4(最終的に採用されたオプション):要約...

ウェブデザインにおけるカラーマッチングの優れた例30選

本日は、色彩の応用に関する優れた事例を 30 件集めて、皆さんにご紹介したいと思います。これらの事例...

Navicat for Mysql 接続エラー 1251 (接続失敗) の問題を解決する

以前書いた内容が詳細さに欠けていたため、今回は修正・補足しました。ただし、以前の MySQL バージ...

CSS のオーバーフロー:hidden エラーの解決方法

失敗の原因今日、カルーセルを書いていたときに、overflow;hidden; が失敗する可能性があ...

純粋なJSを使用してセカンダリメニュー効果を実現します

この記事の例では、セカンダリメニュー効果を実現するためのJSの具体的なコードを参考までに共有していま...

MySQL インデックスの原理と使用例の分析

この記事では、例を使用して MySQL インデックスの原理と使用方法を説明します。ご参考までに、詳細...