MySQL道普請便り

第139回 オンラインスキーママイグレーションツール gh-ostを使ってみよう[その2]

この記事を読むのに必要な時間:およそ 3 分

前回に続いて,オンラインスキーママイグレーションツール gh-ostについて紹介したいと思います。先に,第138回 オンラインスキーママイグレーションツール gh-ostを使ってみよう[その1]をご確認ください。

内部テーブル

gh-ost実行中には内部でテーブルを作成します。実行終了時にはそれらは自動で削除されますが,エラーが発生するとゴミとして残ることがあります。その際は再実行するとエラーとなるので,削除する必要があります。

ここで,どのような内部テーブルを作成するか説明します。

_TABLENAME_ghoテーブル(例._sbtest1_gho)
ゴーストテーブルです。カットオーバー後,基テーブルの名前にリネームされます。--initially-drop-ghost-tableオプションをTrueにした場合,開始時にそれが存在すると削除します。
_TABLENAME_ghcテーブル(例._sbtest1_ghc)
変更ログテーブルです。ステータス情報やレプリケーション遅延を検知するためのデータが格納されています。gh-ostではSHOW SLAVE STATUSseconds_behind_masterでレプリケーション遅延を判定していません。このテーブルに時刻を登録して独自に遅延を判定しています。そのため,ms単位での判定が可能になっています。
_TABLENAME_delテーブル(例._sbtest1_del)
カットオーバー後の基テーブルです。--initially-drop-old-tableオプションをTrueにすると,開始時にそれが存在すると削除します。--ok-to-drop-tableオプションをTrueにすると,実行終了後に削除します。

ステータス情報

標準出力されるログに,ステータス情報が毎秒表示されます。

Copy: 600000/986400 60.8%; Applied: 0; Backlog: 0/1000; Time: 13s(total), 12s(copy); streamer: binary_log.000067:955093716; Lag: 0.02s, State: migrating; ETA: 7s

各ステータスは以下のようになっています。

項目 表示例 内容
Copy Copy: 589300/752865 78.3%; 総行数の推定値のうち,ゴーストテーブルにコピーされた既存のテーブル行数
Applied Applied: 2299; バイナリログを処理して,ゴーストテーブルに適用されたエントリ数
Backlog Backlog: 50/1000; バイナリログのキュー
Time Time: 34s(total), 5s(copy); 経過時間
streamer streamer: mysql-bin.006793:179473435; 現在,gh-ostが処理しているバイナリログエントリ
Lag Lag: 0.21s, レプリケーションラグ
State State: migrating ステータス
ETA ETA: 3m31s 予想終了時間

ステータス情報を取得する方法は,ログだけではなくいくつかあります。

テーブル
_TABLENAME_ghcテーブルを問い合わせることで,ステータス情報を取得できます。
mysql> SELECT value FROM _sbtest0_ghc ORDER BY id DESC LIMIT 1;
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| value                                                                                                                                                                       |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Copy: 2996000/27123408 11.0%; Applied: 0; Backlog: 0/1000; Time: 1m15s(total), 1m14s(copy); streamer: binary_log.000013:243962263; Lag: 0.02s, State: migrating; ETA: 9m55s |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
UNIXソケットファイルやTCP
詳しくは Interactive commands をご確認ください。

スロットル

スロットルとは,gh-ostはレプリケーションの遅延やマスターの負荷を検知して,ハートビートやステータス書き込み以外の動作を停止するスロットリングことで,マスターへの負荷を取り除く機能です。この機能により,マイグレーション中にスパイクするような処理がマスターで発生したとしても,マイグレーションによる負荷の影響を最小限に抑えることが可能です。

さまざまな観点からスロットリングするオプションが存在します。

レプリケーション遅延

レプリケーション遅延を検知して,スロットリングします。

--max-lag-millis
単位はmsで指定した時間レプリケーションが遅延するとスロットリングが開始されます。デフォルトは1500msです。--throttle-control-replicasオプションを使って,遅延をチェックするレプリカを指定することもできます。

負荷

MySQLの負荷を検知して,スロットリングします。

--max-load
コンマ区切りでMySQLのステータス名としきい値を設定し,それを超えるとスロットリングが開始されます。デフォルトは指定なしです。'Threads_running=100,Threads_connected=500'のようにカンマ区切りで複数の設定も可能です。

手動

スロットリングを開始,終了を手動でコントロールすることも可能です。

--throttle-flag-file string
ファイルが存在するとスロットリングが開始されます。デフォルトは指定なしです。たとえば,--throttle-flag-file=/tmp/manual_throttleでgh-ostを実行した場合,touch /tmp/manual_throttleでスロットリング開始,rm /tmp/manual_throttleで終了となります。

クエリ

任意のクエリを実行させて,戻り値が0より大きい数値であるとスロットリング開始します。

--throttle-query string
たとえば,--throttle-query="select hour(now()) between 8 and 17" とすると,スロットリングは午前8:00に自動開始し,マイグレーションは午後18:00に自動再開されることになります。

最小限のオプションでgh-ostを実行しても,デフォルトでレプリケーション遅延の1500msを超えると,スロットリングが開始するようになっていますが,念のため,実行するときは--max-load--throttle-flag-fileは指定したほうが良さそうです。

現在,gh-ostがスロットリングしているかの確認方法としては,ステータス情報のStateがthrottledになります。たとえば,State: throttled, lag=1.581677s;のような表示の場合は,レプリケーション遅延がしきい値を超えたため,スロットリングしていることを意味しています。

カットオーバー

カットオーバーとは,基テーブルとゴーストテーブルを入れ替える最終段階の操作になります。デフォルトは,ゴーストテーブルへのコピーが完了すると即座に入れ替えが行われます。

以下のようなSQLを内部で発行して,テーブルが存在していない期間がないように,基テーブルとゴーストテーブルを同時にリネームします。

rename /* gh-ost */ table sysbenchdb.sbtest1 to sysbenchdb._sbtest1_del, sysbenchdb._sbtest1_gho to sysbenchdb.sbtest1;

いくつかオプションを紹介します。

--cut-over-lock-timeout-seconds int
カットオーバーの試行中にテーブルのロック取得に待機する秒数です。デフォルトは3秒です。lock_wait_timeout値と考えて大丈夫です。
--postpone-cut-over-flag-file=string
マイグレーション開始時に指定したファイルを作成します。それが存在する間,マイグレーションはテーブルの入れ替えを延期し,ゴーストテーブルの同期を継続します。カットオーバーはファイルが削除された瞬間に実行します。

カットオーバーのタイミングをすぐに実行しても良い場合は,デフォルトで大丈夫です。タイミングをこちら側で制御したい場合は,--postpone-cut-over-flag-fileオプションを指定すると良いでしょう。

また,カットオーバーが完了して,アプリケーションはマイグレーションされたテーブルにはじめて触れることになります。よって,アプリケーションでなにか問題が起こるとすると,カットオーバー直後が多いと思います。

マイグレーションの影響でエラーとなっているなら,基テーブルとゴーストテーブルを再度入れ替えることで元の構成に戻ります。先ほどのSQLを逆に書き直して実施すればOKです。

rename table sysbenchdb.sbtest1 to sysbenchdb._sbtest1_gho, sysbenchdb._sbtest1_del to sysbenchdb.sbtest1;

その後,ゴーストテーブルに変更されたデータがすでにある場合などは,手動での同期作業が必要です。

まとめ

今回はgh-ostの機能などについて紹介しました。pt-online-schema-changeではトリガーを使用しているため,一時的にマスターがスパイクすると,トリガによるオーバーヘッドは大きいものでした。gh-ostのスロットル機能では,レプリカからバイナリログを取得するのとマスターへのステータス変更の更新だけなので,マスターへの負荷を最小限に抑えることができる点は良い思います。

次回は注意点などについて紹介したいと思います。

著者プロフィール

北川健太郎(きたがわけんたろう)

LINE株式会社所属のデータベースエンジニア。担当はMySQLとOracle Database。好きなMySQLの機能はレプリケーションで,好きなOracleDatabaseの機能はログオントリガー。

Twitter:@keny_lala