今回から3回に渡って、
はじめに、
しかし、
gh-ostを使用すれば、
アーキテクチャ
gh-ostは基本的に以下のように動作します。
- 変更したいテーブル
(基テーブル) の空のコピーテーブル (ゴーストテーブル) を作成 - ゴーストテーブルに対して指定したALTERステートメント実行
- 基テーブルの既存データをゴーストテーブルにコピー
- マイグレーション実行中、
基テーブルへの新規DMLはバイナリログから抽出し、 ゴーストテーブルへ適用
※ 3と4は並列で稼働します - 3と4が終わると、
基テーブルとゴーストテーブルを入替 (カットオーバー)
オンラインスキーママイグレーションツールとして有名なツールに、
よって、
また、
必須要件
権限の作成
gh-ostを実行するために以下の権限が必要です。
ALTER, CREATE, DELETE, DROP, INDEX, INSERT, LOCK TABLES, SELECT, TRIGGER, UPDATE
の権限を対象のデータベース権限で作成SUPER,REPLICATION CLIENT, REPLICATION SLAVE on *.*
が必要な場合あり
2.の権限が必要な場合は--switch-to-rbr
オプションがTrueのときです。このオプションは、STOP SLAVE
とSTART SLAVE
します。確実にレプリカのbinlog_--assume-rbr
オプションをつけて実行することでSTOP SLAVE
とSTART SLAVE
は実行されませんので、
レプリケーション設定
gh-ostがレプリカからバイナリログを取得するためのMySQLの設定になります。
- レプリカでlog_
binが設定されていること - レプリカでlog_
slave_ updates=ONであること - レプリカでbinlog_
format=ROWであること - レプリカでbinlog_
row_ image=FULLであること
前述の--switch-to-rbr
オプションは、log_
をONへ、binlog_
をFULLにはしてくれません。よって、
また、
ちなみに、
制限事項
下記条件のうちいずれかに当てはまると実行エラーとなります。ご留意ください。
- 対象テーブルにプライマリキーまたはNOT NULL制約がついたユニークキーがない。
- 対象テーブルに外部キー制約がある。
(子テーブル、 親テーブルまたは両方) - 対象テーブルにトリガーがある。
- 対象テーブルのプライマリーキーがJSONカラムの一部から生成されたキーである。
使ってみる
さて、
マスターと必須要件を満たしたレプリカのMySQLを用意します。
インストール
今回は、
# wget https://github.com/github/gh-ost/releases/download/v1.1.0/gh-ost-1.1.0-1.x86_64.rpm # rpm -i gh-ost-1.1.0-1.x86_64.rpm
実行
まずは、
CREATE TABLE `sbtest1` ( `id` int NOT NULL AUTO_INCREMENT, `k` int NOT NULL DEFAULT '0', `c` char(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '', `pad` char(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '', PRIMARY KEY (`id`), KEY `k_1` (`k`) ) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
gh-ost \ --host=192.168.0.2 \ --port=3306 \ --user="ghost_user" \ --password="xx" \ --database="sysbenchdb" \ --alter="ALTER TABLE sbtest1 ADD col1 int;" \ --execute
--host
…レプリカのホスト名。マスターの情報はgh-ostが内部で検索します(default: "127. 0.0. 1") --port
…レプリカのポート番号(default: 3306) --user
…接続するユーザ名--password
…パスワード--database
…データベース名--alter
…実行したいAlterステートメント。--execute
…テーブルの変更と移行を実際に実行。指定なしはテストをして終了
標準出力にログが出力されます。
[2020/12/28 10:51:56] [info] binlogsyncer.go:354 begin to sync binlog from position (binary_log.000012, 732101540) [2020/12/28 10:51:56] [info] binlogsyncer.go:723 rotate to (binary_log.000012, 732101540) # Migrating `sysbenchdb`.`sbtest1`; Ghost table is `sysbenchdb`.`_sbtest1_gho` # Migrating 192.168.0.1:3306; inspecting 192.168.0.2:3306; executing on 192.168.0.3 # Migration started at Mon Dec 28 10:51:56 +0900 2020 # chunk-size: 1000; max-lag-millis: 1500ms; dml-batch-size: 10; max-load: ; critical-load: ; nice-ratio: 0.000000 # throttle-additional-flag-file: /tmp/gh-ost.throttle # Serving on unix socket: /tmp/gh-ost.sysbenchdb.sbtest1.sock Copy: 0/9936 0.0%; Applied: 0; Backlog: 0/1000; Time: 1s(total), 0s(copy); streamer: binary_log.000012:732104613; Lag: 0.02s, State: migrating; ETA: N/A Copy: 0/9936 0.0%; Applied: 0; Backlog: 0/1000; Time: 2s(total), 1s(copy); streamer: binary_log.000012:732112272; Lag: 0.01s, State: migrating; ETA: N/A Copy: 10000/10000 100.0%; Applied: 0; Backlog: 0/1000; Time: 2s(total), 1s(copy); streamer: binary_log.000012:733837596; Lag: 0.01s, State: migrating; ETA: due Copy: 10000/10000 100.0%; Applied: 0; Backlog: 1/1000; Time: 3s(total), 1s(copy); streamer: binary_log.000012:734037044; Lag: 0.01s, State: migrating; ETA: due Copy: 10000/10000 100.0%; Applied: 0; Backlog: 0/1000; Time: 3s(total), 1s(copy); streamer: binary_log.000012:734039306; Lag: 0.01s, State: migrating; ETA: due [2020/12/28 10:51:59] [info] binlogsyncer.go:164 syncer is closing... [2020/12/28 10:51:59] [error] binlogstreamer.go:77 close sync with err: sync is been closing... [2020/12/28 10:51:59] [info] binlogsyncer.go:179 syncer is closed 2020-12-28 10:51:59 ERROR Error 1146: Table 'sysbenchdb._sbtest1_ghc' doesn't exist # Done
このように、# Done
が出力されていれば正常終了となります。
sbtest1テーブルを確認してみます。
CREATE TABLE `sbtest1` ( `id` int NOT NULL AUTO_INCREMENT, `k` int NOT NULL DEFAULT '0', `c` char(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '', `pad` char(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '', `col1` int DEFAULT NULL, PRIMARY KEY (`id`), KEY `k_1` (`k`) ) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
col1カラムが追加されました。
また、
mysql> show tables like '_sbtest1_del'; +-------------------------------------+ | Tables_in_sysbenchdb (_sbtest1_del) | +-------------------------------------+ | _sbtest1_del | +-------------------------------------+
_sbtest1_
は基テーブルです。基本的に_TABLENAME_
という形で残されています。DROPはコストの高い処理のため、--ok-to-drop-table
オプションをつけると実行終了時にDROPされます。
gh-ostを実行する手順として、
- --executeオプションなしで実行して、
エラーがないか確認 - --executeオプションをつけて、
実際に実行する
まとめ
gh-ostの概要と、
次回は、