【MySQL】gh-ostでオンラインマイグレーションの応用編です。
gh-ostはMySQLのバイナリログを使ってテーブルを同期します。
一方で、AWSのAmazon Auroraは、バイナリログを使わない方法でリードレプリカを作成します。
※Auroraのリードレプリカが一体どういう仕組みなのかここでは省きますが、過去のAWS SummitのDeep DiveとかでAmazonの超技術を垣間見ることができます。
[レポート] Amazon Aurora deep dive ~性能向上の仕組みと最新アップデート~ #AWSSummit | Developers.IO
さてバイナリログを使っていないとなると、gh-ostの利用はどうなるのでしょうか。
gh-ostにもドキュメントがありますが
gh-ost has been updated to work with Amazon RDS however due to GitHub not relying using AWS for databases, this documentation is community driven so if you find a bug please open an issue!
(gh-ostはAmazon RDSでも動くようになったが、我々GitHubはDBにAWSは使ってないので、このドキュメントはコミュニティに懸かっている。だからバグを見つけたら是非issueを上げて欲しい)
とあり、gh-ostの特徴のひとつである「GitHub社での実績」が欠けます。
実際に使ってみました。
準備
下記条件でAWS RDS Auroraインスタンスを作ります。
t2.smallインスタンスが解禁されたので、検証用途でもAuroraを作りやすくなりました。
- Aurora 5.6.10a
- db.t2.small
- writer×1、reader×1
また、接続元のIPアドレスを調べてセキュリティグループでポートを開けておきます。
gh-ostを使うにはバイナリログが必要です。
先述のとおりAuroraのリードレプリカ作成にはバイナリログは使われませんが、Auroraと他のMySQL等とのレプリケーションのためにバイナリログの出力機能は存在しています。
Aurora と MySQL との間、または Aurora と別の Aurora DB クラスターとの間のレプリケーション - Amazon Relational Database Service
gh-ostを利用するには、DB Cluster Parameter Groupにて「binlog_format=ROW」に設定しておく必要があります。
クラスターエンドポイントに接続し、show binary logs
でバイナリログファイルが確認できればOKです。
mysql> SHOW VARIABLES LIKE "binlog_format";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
1 row in set (0.01 sec)
mysql> show binary logs;
+----------------------------+-----------+
| Log_name | File_size |
+----------------------------+-----------+
| mysql-bin-changelog.000001 | 120 |
| mysql-bin-changelog.000002 | 16062 |
+----------------------------+-----------+
2 rows in set (0.01 sec)
今回の検証には下記のデータベース/テーブルを使います。
USE sushiya;
CREATE TABLE sushi(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20),
INDEX(id)
);
gh-ostの実行
まず入手します。
$ wget https://github.com/github/gh-ost/releases/download/v1.0.36/gh-ost-binary-linux-20170403125842.tar.gz
$ tar xzvf ./gh-ost-binary-linux-20170403125842.tar.gz
gh-ostには3つのモードがありますが、Aurora上ではb. Connect to masterにて実行します。
$ ./gh-ost \
--user="(ユーザー)" \
--password="(パスワード)" \
--host="(クラスターエンドポイント)" \
--port=3306 \
--database="sushiya" \
--table="sushi" \
--alter="ADD COLUMN price INT DEFAULT 100, ADD COLUMN created_at DATETIME" \
--allow-on-master \
--execute
確認します。
mysql> show create table sushi\G
*************************** 1. row ***************************
Table: sushi
Create Table: CREATE TABLE `sushi` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`price` int(11) DEFAULT '100',
`created_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.01 sec)
カラムが増えていることを確認できました。
gh-ostの特徴としてa. Connect to replica, migrate on masterモードやc. Migrate/test on replicaモードがありますが、これらを使うためにリードレプリカに接続して実行しようとしても「バイナリログが無効」というエラーで失敗してしまいます。
$ ./gh-ost \
> --user="(ユーザー)" \
> --password="(パスワード)" \
> --host="(リーダーエンドポイント)" \
> --port=3306 \
> --database="sushiya" \
> --table="sushi" \
> --alter="ADD COLUMN price INT DEFAULT 100, ADD COLUMN created_at DATETIME" \
> --test-on-replica
2017-05-02 01:11:40 FATAL (リーダーエンドポイント):3306 must have binary logs enabled
もしAuroraからバイナリログを受け取って同期しているSlaveデータベースがあれば、c. Migrate/test on replicaモードでの実行も可能なのではないかと思います。
Interactive commandsの使用
通常のgh-ost利用時と同様に、UNIXドメインソケットを使った制御もAurora経由で可能です。
gh-ost/interactive-commands.md at master · github/gh-ost
テーブル切り替えを保留にするフラグファイルを作成します。
$ touch /tmp/ghost.postpone.flag
実行します。
$ ./gh-ost \
--user="(ユーザー)" \
--password="(パスワード)" \
--host="(クラスターエンドポイント)" \
--port=3306 \
--database="sushiya" \
--table="sushi" \
--alter="ADD COLUMN price INT DEFAULT 100, ADD COLUMN created_at DATETIME" \
--allow-on-master \
--postpone-cut-over-flag-file=/tmp/ghost.postpone.flag \
--execute
--postpone-cut-over-flag-file
オプションで、先程作成したフラグファイルを指定するとテーブルの同期だけが進み、切り替えが保留状態になります。
ここからステータスの確認など、gh-ost実行途中での操作ができます。
$ echo status | nc -U /tmp/gh-ost.sushiya.sushi.sock
unposepone
でテーブルの切り替えが実行されます。
$ echo unpostpone | nc -U /tmp/gh-ost.sushiya.sushi.sock
確認します。
mysql> SHOW CREATE TABLE sushi\G
*************************** 1. row ***************************
Table: sushi
Create Table: CREATE TABLE `sushi` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`price` int(11) DEFAULT '100',
`created_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.01 sec)
カラムが追加されました。
Auroraでgh-ostの必要性がどれくらいあるかはさておき、Auroraでも一部条件下にてgh-ostを利用できることがわかりました。