GCPのMySQL (Cloud SQL)でオンラインマイグレーションする

MySQL on Cloud SQLでオンラインマイグレーションする方法を調べたときのメモです。以下2つのツールを試してみました。

  • pt-online-schema-change
  • gh-ost

対象MySQL

今回は以下の環境を前提としています。

オンラインDDL

オンラインマイグレーションで最初に思いつくのがオンラインDDLです。ドキュメントはこちら、主な制約はこちら に記載されています。

MySQL自体が提供している機能なので何のツールにも依存せず使えるというのが利点です。条件によっては、マイグレーション中のテーブルへのアクセス(並列DML)が可能だったり、テーブルの作り直しが不要でディスクサイズが少なく済む(In Place)更新が可能になります。

ただしオンラインDDLには一つ大きな懸念があります。たとえ Lock=Noneを指定してもオンラインを保てるのはマスターだけの話で、レプリカはマスターのDDL操作が完了するまでDMLの適用をブロックしてしまいます。これによって大きなテーブルに対するDDLが深刻なレプリケーション遅延を発生するリスクを持ちます。

またスロットリングなどができないため、マスターへの負荷を調整できないというリスクもあります。

これらはいずれもCloud SQL固有の問題ではなくMySQL(innodb)一般の話です。

負荷やレプリケーション遅延が問題にならないケースに限ればオンラインDDLでも十分かもしれませんが、そういったケースは多くはないと思います。そこでCloud SQLでも巷のオンラインマイグレーションツールが利用できるのか、軽く試してみました。

pt-online-schema-change (pt-osc)

pt-oscは古くからある人気の(?)オンラインスキーママイグレーションツールです。ドキュメントはこちらにあります。

DDL適用後の新しいスキーマで作業用テーブルを新規に作り、元のテーブルからコピーします。さらにpt-oscはTRIGGERを使って、コピー中に元のテーブルに対する変更も作業用テーブルに伝搬させます。最後にテーブルの名前を変更してテーブルを切り替えます。

pt-oscをCloud SQLで動かす

Cloud SQLで動かそうとしたところ以下の点で注意が必要でした。

1) log_bin_trust_function_creators を有効にする

pt-oscはTRIGGERを作成するため、pt-oscが利用するMySQL ユーザーにSUPER権限を要求します。しかし今の所Cloud SQLではSUPER権限は付与できません。 代わりに log_bin_trust_function_creators フラグを付与することでSUPER権限がなくてもTRIGGERの生成を許可することができます。データベースフラグを更新する方法についてはこちらを確認してください。

2) --check-slave-lag でレプリカを明示的に指定する

pt-oscはレプリカを認識するとレプリケーション遅延を確認して --max-lag 以上になった時、一時停止してスロットリングしてくれます。しかし何も指定せず実行すると以下のようなワーニングが出て、レプリカがうまく認識されませんでした。

そもそもCloud SQL Proxy経由で繋いでいる環境下では、MySQLサーバーから取得できるホスト情報では、pt-osc実行環境から繋ぐことはできなそうです。pt-oscは明示的にスレーブを指定するオプションを用意しているのでそれを使います。 —-check-salve-lag D=foo,h=127.0.0.1,P=33001このようなオプションを追加してうまく認識できました。ワーニングの代わりに以下のようなログが確認できます。

コマンド実行例

gh-ost

pt-oscのようにTRIGGERを利用した方法における問題を避けるため、TRIGGERを利用せずに実装されたオンラインマイグレーションツールです。TRIGGERがどのような問題を引き起こすかはこちらのページに書かれています。

gh-ostのマイグレーションは、DDL適用後の新しいスキーマで作業用テーブルを作り、元のテーブルにコピーしていきます。そしてgh-ost自身がMySQLサーバーに繋いでbinlogイベントを受け取り、コピー中に発生した元テーブルに対する変更を作業テーブルに反映します。最後にcut overと呼ぶ最終ステップでテーブルの切り替えを行います。

pt-oscよりも柔軟なスロットルが可能でマイグレーション中に適用できる様々なインタラクティブコマンドを提供しています。

gh-ostをCloud SQLで動かす

Cloud SQLで動かそうとしたところ以下の点で注意が必要でした。

1) --allow-on-master を指定する

gh-ostは、マイグレーション中のマスターサーバーへの負荷を抑えるためbinlogイベントをレプリカから読むことを推奨しています。 また —-test-on-replica` というモードで、マイグレーションをレプリカ上でテストする機能を提供しています。しかし残念ながら今の所 Cloud SQL はレプリカのレプリカを許可しておらず、マスターからbinlogイベントを受け取る方法しか選択できません。外部レプリカを作ってそこにつなぎに行くという方法もあるようですが、GCPを使ううれしみが半減してしまうので今回は試していません。

マスターに繋ぐためには--allow-on-masterをオプションに指定します。詳しくはこちらのcheatsheetを確認してください。

2)--gcpオプションをつける

Cloud SQL Proxy 環境下では、これをつけないと以下のようなエラーになりました。

gh-ostのドキュメントではこのオプションは第1世代向けのようなことが書かれていましたが、接続をトンネルしてる時(接続に指定したポートと実際にserveしているポートが異なる時)に使えるようです。

コマンド実行例

あとがき

今回本番のワークロード下で試したりはしてないので、まだCloud SQL固有の落とし穴がなにかあるかもしれません。今後も見つけたら更新していこうと思います。

参考リンク

https://github.com/rerorero