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

推薦する

ApacheのDjangoオンライン展開方法

環境: 1. Windows Server 2016 Datacenter 64 ビット 2. SQ...

MySQL 5.7 mysql コマンドラインクライアントの使用コマンドの詳細

MySQL 5.7コマンドを使用するMySQLコマンドラインクライアント1. パスワードを入力してく...

HTMLでは、全体的なスタイルとレイアウトを崩さずに、部分的に強制スクロールバーを使用できます。

まずはエフェクト画像を投稿します:全体的なスタイルとレイアウトが崩れないように、スクロール バーがロ...

Docker で Springboot プロジェクトを実行する実装

導入: springboot プロジェクトを実行する Docker の構成は実は非常にシンプルで、L...

React プロジェクトにおける axios カプセル化と API インターフェース管理の詳細な説明

目次序文インストール導入環境の切り替え傍受を要求するレスポンスインターセプションAPIの統合管理要約...

ウェブサイトを構築するときは、UTF-8 または GB2312 エンコードを使用する必要がありますか?

外国のウェブサイトを開くと文字化けした文字が表示されることが多く、また、英語以外の外国のウェブサイト...

git bash を使用して Linux にログインするための ssh の設定方法

1. まず、Linux サーバー上で公開鍵ファイルと秘密鍵ファイルを生成します。デフォルトの保存ディ...

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

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

スローモーションアニメーション効果を実現するJavaScript

この記事では、スローモーションアニメーション効果を実現するためのJavaScriptの具体的なコード...

Vite2とVue3を使用したウェブサイトの国際化を実現するプロセス全体

目次序文vue-i18nをインストールするロケールの設定getLangs.js の実装i18nインス...

Vue3のサンドボックスの仕組みの詳しい説明

目次序文ブラウザコンパイル版ローカルプリコンパイルバージョン要約する序文vue3サンドボックスには主...

集める価値のある 15 個の JavaScript 関数

目次1. 数字を逆にする2. 配列内の最大のn個の数値を取得する3. 階乗を計算する4. 現在の動作...

リモート接続を許可するようにMySQLを変更する方法

MySQLリモート接続の問題に関しては、会社で働いているときに誰かのコンピュータに保存されているMy...

MySQL 8.0.17 のインストールと使用方法のチュートリアル図

前面に書かれた過去および現在のプロジェクトで最も一般的に使用されているリレーショナル データベースは...

Vue の el-table は自動天井効果を実現します (固定をサポート)

目次序文実装のアイデア効果:使用:メインソースコード:序文多くのケースを見た結果、単純な観点からは、...