MySQL道普請便り

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

前回に続いて、オンラインスキーママイグレーションツール 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のスロットル機能では、レプリカからバイナリログを取得するのとマスターへのステータス変更の更新だけなので、マスターへの負荷を最小限に抑えることができる点は良い思います。

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

おすすめ記事

記事・ニュース一覧