mita2 database life

主にMySQLに関するメモです

TiDB metadata lock 有効な場合の DDL の挙動

TiDB の DDL の挙動を確認した。

まとめ

  • tidb_enable_metadata_lock が有効だと、DDLは先行のトランザクションによって待たされることがある
  • metadata lock 待ちが発生していても、(MySQL と違って) DMLは影響を受けない
  • metadata lock の状況は mysql.tidb_mdl_view で観測できる
    • (MySQL と違って) SHOW PROCESSLIST では表示されない

環境

TiDB 8.0.11 / tidb_enable_metadata_lock = ON で試します。tidb_enable_metadata_lock はデフォルト で ON です。

mysql> SHOW GLOBAL VARIABLES LIKE 'version';
+---------------+--------------------+
| Variable_name | Value              |
+---------------+--------------------+
| version       | 8.0.11-TiDB-v8.0.0 |
+---------------+--------------------+
1 row in set (0.02 sec)

mysql> SHOW GLOBAL VARIABLES LIKE 'tidb_enable_metadata_lock';
+---------------------------+-------+
| Variable_name             | Value |
+---------------------------+-------+
| tidb_enable_metadata_lock | ON    |
+---------------------------+-------+
1 row in set (0.03 sec)

検証

ロングトランザクションを実行開始し、ALTER TABLEを別セッションで実行します。

mysql> BEGIN;
Query OK, 0 rows affected (0.02 sec)

mysql> UPDATE t1 SET c1 = 'updated' WHERE pk = 1;
Query OK, 1 row affected (0.08 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql>  ALTER TABLE t1 MODIFY COLUMN c2 INT NULL;

ALTER TABLE は先行するトランザクションが終わるまで、metadata lock 待ちで待たされます。 metadata lock で待たされている様子は、(MySQL と違って) SHOW PROCESSLIST には表示されません。

-- ALTER TABLE は待たされているが、SHOW PROCESSLIST では観測できない
mysql> SHOW PROCESSLIST;
+------------+------+-----------------+------+---------+------+----------------------------+------------------------------------------+
| Id         | User | Host            | db   | Command | Time | State                      | Info                                     |
+------------+------+-----------------+------+---------+------+----------------------------+------------------------------------------+
| 1497366540 | root | 127.0.0.1:38330 | test | Sleep   |   76 | in transaction; autocommit | NULL                                     |
| 1497366538 | root | 127.0.0.1:49314 | test | Query   |    6 | autocommit                 | ALTER TABLE t1 MODIFY COLUMN c2 INT NULL |
| 1497366546 | root | 127.0.0.1:50144 | test | Query   |    0 | autocommit                 | SHOW PROCESSLIST                         |
+------------+------+-----------------+------+---------+------+----------------------------+------------------------------------------+
3 rows in set (0.01 sec)

tidb_mdl_view で、metadata lock 待ちを観測できます。SQL_DIGESTS でブロックしているトランザクションの内容が見れるのは便利ですね。

mysql> SELECT * FROM mysql.tidb_mdl_view \G
*************************** 1. row ***************************
     job_id: 120
    db_name: test
 table_name: t1
      query: ALTER TABLE t1 MODIFY COLUMN c2 INT NULL
 session_id: 1497366540
 start_time: 2024-05-01 03:41:18.621000
SQL_DIGESTS: ["begin","update `t1` set `c1` = ? where `pk` = ?"]
1 row in set (0.20 sec)

ALTER TABLE が待たされている状態で、後続のDMLALTER TABLE の完了を待つかどうかを確認します。

mysql> UPDATE t1 SET c1 = 'updated' WHERE pk = 10;
Query OK, 1 row affected, 1 warning (0.22 sec)
Rows matched: 1  Changed: 1  Warnings: 1

→ 待たされませんでした。

先行するトランザクションCOMMIT すると、ALTER TABLE が開始されます。 なお、ALTER TABLEが開始されても、DMLはブロックされることなくオンラインで実行可能です。