Percona Toolkit pt-online-schema-change でサービス無停止スキーマ変更

テーブルにカラムやインデックスを追加するといった、いわゆるスキーマの変更を行うときは、通常、サービスをメンテナンスに入れてから作業をしなくてはいけません。理由は、ALTER TABLE実行中は共有ロックがかかってしまうため、更新クエリを実行しても即座に完了しなくなるからです。そうすると、アプリからみればおそらく更新クエリを発行するページではHTTPタイムアウトになりますし、参照だけのページでもかなり遅くなることでしょう。

サービスの改良をすると必ずスキーマ変更が必要になりますが、しかしサービスは可能な限り24時間365日提供したいもの。Percona Toolkitの pt-online-schema-change はそんな悩みを払拭し、サービスを停止すること無くスキーマの変更を可能にしてくれます。



概要と仕組み

Percona Toolkitは全てPerlスクリプトなので、/usr/bin/pt-online-schema-change を見れば詳細を確認できます。仕組みを簡単に説明すると、

  1. 既存テーブルのスキーマをコピーして新規テーブルを作成
  2. 新規テーブルにスキーマ変更を適用
  3. トリガーを作成して既存テーブルへの変更を新規テーブルに反映される状態に
  4. 既存テーブルから新規テーブルへデータをコピー
  5. コピーが完了したらRENAMEにより既存テーブルをどけて新規テーブルを正規の名前にする
  6. 旧テーブルとトリガーを削除する

この手順でやればオンラインで実行できますよ、という手順を1つのスクリプトにしてくれただけなので、XtraDBである必要はありません。軽くまとめると、

メリット

  • 共有ロック不要でスキーマ変更できる
  • 実行中に進行割合を確認できる

  • デメリット

  • 直接 ALTER TABLE を実行するよりは時間がかかる
  • 実行中はコピーとトリガーの分、サーバが高負荷状態になる(少なくとも通常のALTERと同程度)
  • 一時的にテーブルのコピーを作成するため、余分なディスク容量が必要


  • 実行実績

    実行時間

    1GB / 440万行 のテストデータに対する ADD COLUMN で、他クエリの実行なしで
  • 直接実行 : 59秒
  • pt-online-schema-change : 70秒

  • とある本番サーバの約1億行に対する実行では、
  • メンテに入ってから直接実行 : 30分
  • pt-online-schema-change : 45分

  • サービスへの影響

    オンラインと銘打っても、重たい処理に変わりはないのでサービスへの影響はあります。CPUはもちろん、特にDiskI/Oが高くなり、その度合は後述する実際の実行クエリで感触を掴んでもらえればと思います。

    具体的には、ある本番サーバでの例として、
  • pt-online-schema-change を実行中にHTTP Timeoutと判断された量が 0.1~0.5%
  • 最後のRENAMEのタイミングでAPサーバのunicorn workerが再起動する現象を確認

  • もちろん、現象や度合いについては環境次第になるでしょうが、影響は少なからずあることを知り、影響をより少なくする努力をすること。そして場合によっては無理せずメンテナンス状態で実行するという判断をすることが大切になります。


    使い方

    このsysbenchで作成したテーブルの、Field c の後ろに Field new_column を追加するとします。

    接続情報と、D=dbname, t=tablename、そして –after にALTER TABLE tablename に続くSQLを書きます。

    そして最初は –dry-run でテストします。
    これは CRAETE TABLE と ALTER TABLE まで確かめて終了するオプションで、既に存在するカラム名やインデックスといった場合にエラーを返してくれます。

    問題なければ、–dry-run を –execure に変更して実行します。

    完了したら、スキーマの確認をします。


    実行内容の確認

    何が実行されたかは、スクリプトを読むよりも、general_log ON にしてから実行する方が手っ取り早いです。

    これは 1GB 440万行 のテストデータに対するログです。


    ロックの確認

    通常の ALTER TABLE と pt-online-schema-change の処理中それぞれで発行した更新クエリがどうなっているか確認しておきます。

    まず、直接ALTER TABLEを実行しつつ更新クエリを発行すると

    次に、pt-online-schema-change 実行中に更新クエリを発行

    更新クエリが通ることが確認できました。

    あとは変更内容に応じて、RENAME の後でAPサーバからのクエリがエラーにならないような内容にしておけばOKです。



    実行するのは簡単なツールですが、内容を正しく理解しておかないと予期せぬ状態になったり、不測の事態に対応できないので、おいそれと利用するものではないです。でもこのツールを通じてSQLの理解を深められるし、便利だしなので、なんにせよ使ってみたらいいツールだと思います。

    先日の、MySQL Connect 2012で ALTER TABLE がオンラインでできるようになる、と発表されたのでネタが腐る前に掲載してみました。

  • MySQL Connect 2012での発表事項 | rkajiyamaの日記
  • [PDF] MySQL Innovation Day InnoDB Online Operations

  • 仕組みとしては似ているようですが、どんなものか楽しみですね。

    1) Wait for all transactions that have modified the table to complete.
      • Block any transactions that try to modify the table after the ALTER begins.
      • Allow SELECTs from the table, though.
    2) Create a temporary table with the new definition, and copy data from the old table to the new table.
    3) Wait for all remaining transactions against the table to complete, and swap the old and the new table.