はじめに
2022 年 5 月 20 日に GA となった MariaDB 10.8 では、新しく以下の機能が追加されています。
Lag free ALTER TABLE in replication
- Normally, ALTER TABLE gets fully executed on the primary first and only then it is replicated and starts executing on replicas. With this feature ALTER TABLE gets replicated and starts executing on replicas when it starts executing on the primary, not when it finishes. This way the replication lag caused by a heavy ALTER TABLE can be completely eliminated (MDEV-11675).
引用元 : Changes and Improvements in MariaDB 10.8
通常のレプリケーションにおいて、ALTER TABLE はソースで実行が完了してからレプリカに伝播されます。
この機能を使うことで、ソースで ALTER TABLE が実行されたタイミングでレプリカでも同時に実行されるため、ALTER TABLE 実行時のレプリケーション遅延をなくすことが出来るようです。
ALTER TABLE 実行時のレプリケーション遅延についてはよく問題になっており、オンライン DDL 機能や Percona Toolkit の pt-online-schema-change コマンドなどを利用することで、ある程度対策を取ることが可能です。
また、この他に gh-ost というツールもあり、以前弊社ブログでも紹介させていただいています。
今回は、MariaDB において新しく実装されたこの Lag free ALTER TABLE について、利用方法や条件などを確認していきたいと思います。
検証
検証をおこなおうため、公式で公開されている実装の詳細を確認したところ、利用方法として以下の内容が記載されていました。
Usage:- Using this feature is quite simple.
- On master you have to turn on
BINLOG_SPLIT_ALTER
dynamic variable.- Slave must be using parallel replication.
引用元 : Lag Free ALTER Table for Slave
しかし、ソースで設定するとされている BINLOG_SPLIT_ALTER については、 MariaDB 10.8 や 10.9 では実装されていないようでした。
幸い、MariaDB 10.8 の RC リリース時の資料に記載を見つけることができました。
New Features in Community Server 10.8 RC
(…)
For DevOps and DBAs
- New optimistic ALTER TABLE for replicas. When enabled by binlog_alter_two_phase = 1 (not default), an ALTER TABLE is executed on the primary server and is replicated and “started” on the replica server more or less in parallel to the primary server. Thus, the possibly huge replication lag between a primary and replica server due to a long running ALTER TABLE on the primary can be avoided.
引用元 : Announcing MariaDB Community Server 10.7 GA and 10.8 RC
この記載によると、binlog_alter_two_phase を有効にすることで、 Lag free ALTER TABLE を利用することができるようです。
環境
今回、以下のレプリケーション環境で検証をおこないました。
- ソース
- バージョン : MariaDB 10.9.3
- レプリカ
- バージョン : MariaDB 10.9.3
- slave_parallel_workers=4 を設定
検証内容
まずは、通常の ALTER TABLE の動作を確認していきます。
ソース側で、以下のように ALTER TABLE を実行します。
1 2 3 |
MariaDB [(none)]> ALTER TABLE test.t1 ENGINE = InnoDB; Query OK, 0 rows affected (12.262 sec) Records: 0 Duplicates: 0 Warnings: 0 |
すると、実行完了直後は、レプリカ側でレプリケーション遅延が発生していることがわかります。
1 2 3 4 |
MariaDB [(none)]> SHOW SLAVE STATUS\G *************************** 1. row *************************** (...) Seconds_Behind_Master: 71 |
それでは、Lag free ALTER TABLE を利用するために binlog_alter_two_phase を有効にして、再度 ALTER TABLE を実施します。
1 2 3 4 5 6 |
MariaDB [(none)]> SET binlog_alter_two_phase = 1; Query OK, 0 rows affected (0.000 sec) MariaDB [(none)]> ALTER TABLE test.t2 ENGINE = InnoDB; Query OK, 0 rows affected (12.814 sec) Records: 0 Duplicates: 0 Warnings: 0 |
すると、実行完了直後でも、レプリカ側ではレプリケーション遅延が発生していないことが確認できました。
1 2 3 4 |
MariaDB [(none)]> SHOW SLAVE STATUS\G *************************** 1. row *************************** (...) Seconds_Behind_Master: 0 |
また、ソース側で ALTER TABLE を実行している際、既にレプリカ側でも ALTER TABLE が実行されていることがわかります。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
MariaDB [(none)]> SHOW PROCESSLIST; +----+-------------+-----------+------+--------------+-------+--------------------------------------------------------+-------------------------------------+----------+ | Id | User | Host | db | Command | Time | State | Info | Progress | +----+-------------+-----------+------+--------------+-------+--------------------------------------------------------+-------------------------------------+----------+ | 18 | system user | | NULL | Slave_IO | 53322 | Waiting for master to send event | NULL | 0.000 | | 20 | system user | | NULL | Slave_worker | 53322 | Waiting for work from SQL thread | NULL | 0.000 | | 21 | system user | | NULL | Slave_worker | 53322 | Waiting for work from SQL thread | NULL | 0.000 | | 22 | system user | | NULL | Slave_worker | 53322 | Waiting for work from SQL thread | NULL | 0.000 | | 23 | system user | | | Slave_worker | 12 | altering table | ALTER TABLE test.t2 ENGINE = InnoDB | 0.000 | | 19 | system user | | NULL | Slave_SQL | 1372 | Slave has read all relay log; waiting for more updates | NULL | 0.000 | | 29 | root | localhost | NULL | Query | 0 | starting | SHOW PROCESSLIST | 0.000 | +----+-------------+-----------+------+--------------+-------+--------------------------------------------------------+-------------------------------------+----------+ 7 rows in set (0.000 sec) |
動作詳細
実装の詳細によると、binlog_alter_two_phase を有効にすることで、ALTER TABLE を実行した際に以下の 2 つのフェーズに分割して実行されるようになるようです。
- START ALTER
- COMMIT/ROLLBACK ALTER
Desc:- This will split Alter into 2 different commits. START ALTER and COMMIT
/ROLLBACK ALTER , Start Alter will be written in binlog as soon as we get the
locks for the table, alter will proceeds as usual and at the time of writing
binlog if alter is successful we will write COMMIT Alter other wise ROLLBACK
Alter.
引用元 : Lag Free ALTER Table for Slave
これは、実際にバイナリログのイベントから確認することができます。
1 2 3 4 5 6 7 8 9 10 |
MariaDB [(none)]> show binlog events in 'mysql-bin.000003'; +------------------+-----+-------------------+-----------+-------------+-----------------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +------------------+-----+-------------------+-----------+-------------+-----------------------------------------------+ (...) | mysql-bin.000003 | 683 | Gtid | 1 | 725 | GTID 0-1-99 START ALTER | | mysql-bin.000003 | 725 | Query | 1 | 825 | ALTER TABLE test.t2 ENGINE = InnoDB | | mysql-bin.000003 | 825 | Gtid | 1 | 870 | GTID 0-1-100 COMMIT ALTER id=99 | | mysql-bin.000003 | 870 | Query | 1 | 987 | ALTER TABLE test.t2 ENGINE = InnoDB | +------------------+-----+-------------------+-----------+-------------+-----------------------------------------------+ |
なお、ALTER TABLE の実行が失敗した場合は ROLLBACK ALTER が発行されて ALTER TABLE が取り消されるので、データ不整合が発生する心配はなさそうです。
1 2 3 4 5 6 7 8 9 10 |
MariaDB [(none)]> ALTER TABLE test.t2 ENGINE = InnoDB; ^CCtrl-C -- query killed. Continuing normally. ERROR 1317 (70100): Query execution was interrupted MariaDB [(none)]> MariaDB [(none)]> show binlog events in 'mysql-bin.000003'; (...) | mysql-bin.000003 | 1029 | Query | 1 | 1129 | ALTER TABLE test.t2 ENGINE = InnoDB | | mysql-bin.000003 | 1129 | Gtid | 1 | 1174 | GTID 0-1-102 ROLLBACK ALTER id=101 | | mysql-bin.000003 | 1174 | Query | 1 | 1282 | ALTER TABLE test.t2 ENGINE = InnoDB | +------------------+------+-------------------+-----------+-------------+-----------------------------------------------+ |
まとめ
ここまで、MariaDB 10.8 で実装された Lag free ALTER TABLE の動作について確認してきました。
ソースで実行されたタイミングでレプリカでも実行するという動作はシンプルですが、ROLLBACK 時のデータ不整合は発生しないようになっているため、使用できる場面は多いのではないでしょうか。
また、今回は検証できませんでしたが、ソースとレプリカで各種システム変数やサーバースペックが異なっていると、ALTER TABLE の実行にかかる時間は異なってしまうため、レプリケーション遅延やエラーに繋がる可能性がある点にはご注意ください。
なお、公式のリファレンスにはあまり詳しい説明がなく、binlog_alter_two_phase についても特に記載されていないようです。
そのため、本番環境で利用される場合は、十分に動作を検証した上で利用されることをお勧めいたします。