今日はなにの日。

気になったこと勉強になったことのメモ。

今日は、気になってのでMySQLのメタデータロック(MDL)を調べてみたの日。

目次

とある日

メタデータロック(MDL)という言葉を見つけました。

気になったので調べた記録です。

メタデータロック(MDL)とは?

別のトランザクションによって同時に使用されているテーブルでの DDL 操作を防止するタイプのロック。 詳細は、セクション8.11.4「メタデータのロック」を参照してください。

オンライン操作への拡張機能は (特に MySQL 5.6 以降)、メタデータロックの量を減らすことに注力しています。 その目標は、ほかのトランザクションによってテーブルに照会や更新などが行われている間に、テーブル構造を変更しない DDL 操作 (InnoDB テーブルに対する CREATE INDEXDROP INDEX など) を進行できるようにすることです。

MySQL :: MySQL 8.0 リファレンスマニュアル :: MySQL 用語集

メタデータとは

メタデータは「データに関するデータ」です。データベースについて記述しているすべてのものがメタデータであり、データベースの内容ではありません。したがって、カラム名、データベース名、ユーザー名、バージョン名、および SHOW の文字列結果のほとんどがメタデータです。INFORMATION_SCHEMA 内のテーブルは定義上、データベースオブジェクトに関する情報を含んでいるので、これは、このテーブルの内容にも当てはまります。

MySQL :: MySQL 5.6 リファレンスマニュアル :: 10.1.12 メタデータ用の UTF-8

普通のロックとの違い

「データ」にフォーカスするか、「テーブルスキーマにフォーカスしているかの違い。

メタデータロックしてみる

ロックという概念と同じなので、トランザクションを開始して別トランザクションからDDLSQLを実行しています。

トランザクション開始

テーブルはテスト環境にあった適当なやつを使ってます。(意図はないです)

(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 テーブル