今日は、気になってのでMySQLのメタデータロック(MDL)を調べてみたの日。
目次
とある日
メタデータロック(MDL)という言葉を見つけました。
気になったので調べた記録です。
メタデータロック(MDL)とは?
別のトランザクションによって同時に使用されているテーブルでの DDL 操作を防止するタイプのロック。 詳細は、セクション8.11.4「メタデータのロック」を参照してください。
オンライン操作への拡張機能は (特に MySQL 5.6 以降)、メタデータロックの量を減らすことに注力しています。 その目標は、ほかのトランザクションによってテーブルに照会や更新などが行われている間に、テーブル構造を変更しない DDL 操作 (
InnoDB
テーブルに対するCREATE INDEX
やDROP INDEX
など) を進行できるようにすることです。
メタデータとは
メタデータは「データに関するデータ」です。データベースについて記述しているすべてのものがメタデータであり、データベースの内容ではありません。したがって、カラム名、データベース名、ユーザー名、バージョン名、および
SHOW
の文字列結果のほとんどがメタデータです。INFORMATION_SCHEMA
内のテーブルは定義上、データベースオブジェクトに関する情報を含んでいるので、これは、このテーブルの内容にも当てはまります。
普通のロックとの違い
- ロック
- メタデータロック
「データ」にフォーカスするか、「テーブルスキーマ」にフォーカスしているかの違い。
メタデータロックしてみる
ロックという概念と同じなので、トランザクションを開始して別トランザクションからDDLのSQLを実行しています。
トランザクション開始
テーブルはテスト環境にあった適当なやつを使ってます。(意図はないです)
(root@localhost) [test] 8.0.29 > BEGIN; Query OK, 0 rows affected (0.00 sec) (root@localhost) [test] 8.0.29 *> select * from roku limit 10; +-------+----------------------------+ | id | create_at | +-------+----------------------------+ | 1 | 2022-05-18 07:18:10.133200 | | 12615 | 2022-05-18 07:53:53.000008 | | 32173 | 2022-05-18 07:53:53.000009 | | 65846 | 2022-05-18 07:53:53.000012 | | 72612 | 2022-05-18 07:53:53.000013 | | 74 | 2022-05-18 07:53:53.000021 | | 77512 | 2022-05-18 07:53:53.000048 | | 19533 | 2022-05-18 07:53:53.000056 | | 25579 | 2022-05-18 07:53:53.000066 | | 15456 | 2022-05-18 07:53:53.000077 | +-------+----------------------------+
metadata_locksテーブル確認
パフォーマンススキーマは、
metadata_locks
テーブルを介してメタデータロック情報を公開しますMySQL :: MySQL 8.0 リファレンスマニュアル :: 27.12.13.3 metadata_locks テーブル
(root@localhost) [test] 8.0.29 *> SELECT * FROM performance_schema.metadata_locks\G *************************** 1. row *************************** OBJECT_TYPE: TABLE OBJECT_SCHEMA: test OBJECT_NAME: roku COLUMN_NAME: NULL OBJECT_INSTANCE_BEGIN: 139761726085552 LOCK_TYPE: SHARED_READ LOCK_DURATION: TRANSACTION LOCK_STATUS: GRANTED SOURCE: sql_parse.cc:5981 OWNER_THREAD_ID: 47 OWNER_EVENT_ID: 23
別トランザクションからDDL実行
適当にインデックスを作成してみましたが、永遠と終わらなかったです。
(root@localhost) [test] 8.0.29 > create index id_index2 on roku(create_at); ^C^C -- query aborted
調べると、lock_wait_timeout
でメタデータロック取得の待機時間を設定しているようです。
デフォルトは31536000秒(1年)です。
待ってられないので、短くします。
lock_wait_timeout修正
適当に短く設定します。
(root@localhost) [test] 8.0.29 > set lock_wait_timeout = 10; Query OK, 0 rows affected (0.00 sec)
再度別トランザクションからDDL実行
実行して暫く待つと怒られます。
(root@localhost) [test] 8.0.29 > create index id_index2 on roku(create_at); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
〆
データのトランザクションに対してロックするのは既知の挙動でしたが、確かにスキーマも変わると不都合があるのでロックが必要だなとふと思ったので調べました。
インストゥルメントされたオブジェクトの名前。
の「インストゥルメント」が何かわからん。
参考記事
MySQL ::MySQL8.0リファレンスマニュアル::8.11.4メタデータのロック
日々の覚書: MySQL 8.0 vs 外部キー制約 vs ALTER TABLEでメタデータロック待ちになったら疑うこと
MySQL 8.0 への移行が完了しました ~さようなら全ての MySQL 5.7~ - Cybozu Inside Out | サイボウズエンジニアのブログ
第75回 MySQLのさまざまなタイムアウトオプションについて:MySQL道普請便り|gihyo.jp … 技術評論社
MySQL :: MySQL 8.0 リファレンスマニュアル :: 27.12.13.3 metadata_locks テーブル