MySQL道普請便り

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

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

今回から3回に渡って,GitHub社がOSSとして公開しているオンラインスキーママイグレーションツール gh-ostについて紹介したいと思います。

はじめに,MySQLのオンラインスキーママイグレーションというとMySQL 5.6からオンラインDDLがあります。これにより,並列でDMLが実行されてもロックすることなくスキーマ変更が可能です。特に,MySQL 8.0からのInstance Add Columnは,テーブルをリビルドすることなく即時でカラム追加が完了するといううれしい機能です。

しかし,int型からbigint型へなどの型変更を伴うALTERステートメントなど,いくつかの操作は並列のDMLが許可されない,つまりそのテーブルが全体ロックされるような動作になります。加えて,レプリケーションの遅延が発生する可能性もあります。このように,操作の種類によってAlter中にできる動作が異なるのです。これらについては第30回 InnoDBオンラインDDLについてをご参照ください。

gh-ostを使用すれば,いくつか制限はありますが,ALTERステートメントをレプリケーションの遅延や負荷をコントロールしつつ,かならず並列のDMLが許可されるので,サービス稼働中であっても意識することなくスキーママイグレーションが可能です。

アーキテクチャ

gh-ostは基本的に以下のように動作します。

  1. 変更したいテーブル基テーブルの空のコピーテーブルゴーストテーブルを作成
  2. ゴーストテーブルに対して指定したALTERステートメント実行
  3. 基テーブルの既存データをゴーストテーブルにコピー
  4. マイグレーション実行中,基テーブルへの新規DMLはバイナリログから抽出し,ゴーストテーブルへ適用
    ※ 3と4は並列で稼働します
  5. 3と4が終わると,基テーブルとゴーストテーブルを入替カットオーバー

オンラインスキーママイグレーションツールとして有名なツールに,Percona社が公開しているpt-online-schema-change(以降,pt-osc)があります。pt-oscとgh-ostのアーキテクチャーは似ていますが,違いは上記4.の新規DMLの適用方法になります。pt-oscはトリガーを基テーブルに仕掛けて適用させます。gh-ostは自身をレプリカのように振る舞いバイナリログを転送してもらい,そこから抽出して適用します。

よって,トリガーによるオーバヘッドがない分gh-ostのほうが負荷を抑えつつ,柔軟に負荷をハンドリングスロットルできるようになっています。

また,gh-ostは極力マスターの負荷を抑えるためにレプリカを活用するように設計されています。つまり,デフォルトではバイナリログを取得してくる先はレプリカです。よって,1,2,3,5はマスター上で実行され,4のバイナリログの取得はレプリカから,適用はマスターへというようになっています。もちろん,設定によってマスターからバイナリログを取得することも可能ですが,以降の説明はレプリカから取得する設定で進めていきます。

必須要件

権限の作成

gh-ostを実行するために以下の権限が必要です。

  1. ALTER, CREATE, DELETE, DROP, INDEX, INSERT, LOCK TABLES, SELECT, TRIGGER, UPDATEの権限を対象のデータベース権限で作成
  2. SUPER,REPLICATION CLIENT, REPLICATION SLAVE on *.*が必要な場合あり

2.の権限が必要な場合は--switch-to-rbrオプションがTrueのときです。このオプションは,もしレプリカのbinlog_formatがROWでない場合,gh-ostはbinlog_formatをROWに変更してSTOP SLAVESTART SLAVEします。確実にレプリカのbinlog_formatがROWであるならば,--assume-rbrオプションをつけて実行することでSTOP SLAVESTART SLAVEは実行されませんので,権限は不要です。

レプリケーション設定

gh-ostがレプリカからバイナリログを取得するためのMySQLの設定になります。

  1. レプリカでlog_binが設定されていること
  2. レプリカでlog_slave_updates=ONであること
  3. レプリカでbinlog_format=ROWであること
  4. レプリカでbinlog_row_image=FULLであること

前述の--switch-to-rbrオプションは,binlog_formatをROWに変更しますが,log_slave_updatesをONへ,binlog_row_imageをFULLにはしてくれません。よって,先にレプリカで設定してgh-ostを実行するほうが良いでしょう。

また,マスターがステートメントベースレプリケーション(binlog_format=STATEMENT or MIXED)で運用されていたとしても問題ありません。そのレプリカを上記の設定に変更すれば,gh-ostを実行することができます。マスターとレプリカ間で設定が異なるのが嫌だという方は,gh-ost実行後に設定を戻せば大丈夫です。

ちなみに,1,2はMySQLの再起動が必要で,3,4はオンラインで設定変更可能ですが,設定変更後にレプリケーションの再起動(STOP SLAVE,START SLAVE)が必要です。

著者プロフィール

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

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

Twitter:@keny_lala