sgykfjsm.github.com

Amazon RDSのMySQLでオンラインメンテをどうやればいいかを調べた

RDSのMySQLでオンラインメンテ、つまり無停止でのスキーマ変更などをどうやれば良いか、という話。 今までは色々小細工をして生のALTER文を発行していたけど、さすがにロック時間とかが気になり始めたので調べた次第。 ざっとググると、pt-online-schema-changeというツールを使うと良さそうだったので、ここにその作業ログを残す。 以下は参考にしたブログ記事など。

なお、別のツールでoak-online-alter-tableというものがある。oak-online-alter-tableに関する記事は以下が参考になる。

事前準備

pt-online-schema-changeの実行に必要なモジュールがあるかを確認する。

$ perl -MDBD::mysql
Can't locate DBD/mysql.pm in @INC (@INC contains: /Library/Perl/5.12/darwin-thread-multi-2level /Library/Perl/5.12 /Network/Library/Perl/5.12/darwin-thread-multi-2level /Network/Library/Perl/5.12 /Library/Perl/Updates/5.12.5 /System/Library/Perl/5.12/darwin-thread-multi-2level /System/Library/Perl/5.12 /System/Library/Perl/Extras/5.12/darwin-thread-multi-2level /System/Library/Perl/Extras/5.12 .).
BEGIN failed--compilation aborted.

今回は上記の通り、DBD::mysqlがなかったので、cpanmでインストールした。

pt-online-schema-changeを入手する。

$ wget percona.com/get/pt-online-schema-change
$ chmod a+x pt-online-schema-change

今回は以下の様な感じでテスト用のインスタンスを作った。意図せずv5.6になった…。

$ rds-create-db-instance --db-instance-identifier sbtest --db-instance-class db.m1.small --db-name db_sbtest --engine MySQL --allocated-storage 10 --master-username sbtest_user --master-user-password sbtest_passwd
  DBINSTANCE  sbtest  db.m1.small  mysql  10  sbtest_user  creating  1  ****  n  5.6.13  general-public-license  y
        SECGROUP  default  active
        PARAMGRP  default.mysql5.6  in-sync
        OPTIONGROUP  default:mysql-5-6  in-sync

RDSへの対応について

チューニングを行っていない場合、Parameter Groupはデフォルトのままなので、pt-online-schemaを使うためには以下の対応を行う必要がある。

  • メンテナンス用のパラメータグループを作る。(rds-create-db-parameter-group)
  • メンテナンス用のパラメータグループの設定を行う。name=log_bin_trust_function_creators,value=trueを指定する。(rds-modify-db-parameter-group)
  • メンテナンス対象のDBインスタンスのパラメータグループをメンテナンス用のものに変更する。(rds-modify-db-instance)

コマンドで言うと、以下の様なことを行なう。

$ rds-create-db-parameter-group --db-parameter-group-family mysql5.6 --db-parameter-group-name maintenace-pramas-group --description 'parameter group for maintenace '
DBPARAMETERGROUP  maintenace-pramas-group  mysql5.6  parameter group for maintenace
rds-modify-db-parameter-group --db-parameter-group-name maintenace-pramas-group --region us-east --parameters 'name=log_bin_trust_function_creators, value=true, method=immediate'
$ rds-modify-db-parameter-group --db-parameter-group-name maintenace-pramas-group --parameters 'name=log_bin_trust_function_creators,value=true,method=immediate'
DBPARAMETERGROUP  maintenace-pramas-group
$ rds-modify-db-instance --db-instance-identifier sbtest --db-parameter-group-name maintenace-pramas-group --apply-immediately true
DBINSTANCE  sbtest  2014-01-22T13:52:26.982Z  db.m1.small  mysql  10  sbtest_user  available  sbtest.cfscsg6f7tbd.us-east-1.rds.amazonaws.com  3306  us-east-1a  1  n  5.6.13  general-public-license  y
      SECGROUP  default  active
      PARAMGRP  maintenace-pramas-group  applying
      OPTIONGROUP  default:mysql-5-6  in-sync
$ rds-describe-db-instances sbtest
DBINSTANCE  sbtest  2014-01-22T13:52:26.982Z  db.m1.small  mysql  10  sbtest_user  available  sbtest.cfscsg6f7tbd.us-east-1.rds.amazonaws.com  3306  us-east-1a  1  n  5.6.13  general-public-license  y
      SECGROUP  default  active
      PARAMGRP  maintenace-pramas-group  pending-reboot
      OPTIONGROUP  default:mysql-5-6  in-sync

pending-rebootと出ているので、インスタンスを再起動する。

$ rds-reboot-db-instance sbtest
DBINSTANCE  sbtest  2014-01-22T13:52:26.982Z  db.m1.small  mysql  10  sbtest_user  rebooting  sbtest.cfscsg6f7tbd.us-east-1.rds.amazonaws.com  3306  us-east-1a  1  n  5.6.13  general-public-license  y
      SECGROUP  default  active
      PARAMGRP  maintenace-pramas-group  pending-reboot
      OPTIONGROUP  default:mysql-5-6  in-sync
$ rds-describe-db-instances sbtest
DBINSTANCE  sbtest  2014-01-22T13:52:26.982Z  db.m1.small  mysql  10  sbtest_user  rebooting  sbtest.cfscsg6f7tbd.us-east-1.rds.amazonaws.com  3306  us-east-1a  1  n  5.6.13  general-public-license  y
      SECGROUP  default  active
      PARAMGRP  maintenace-pramas-group  in-sync
      OPTIONGROUP  default:mysql-5-6  in-sync

in-syncとなっていることを確認する。

実行

pt-online-schemaを実行する際に、alter文で列のrenameを行なうとき(あるいはchange columnを行なうとき?)には以下のログが出る。

The tool should handle this correctly, but you should test it first because if it fails the renamed columns' data will be lost!  Specify --no-check-alter to disable this check and perform the --alter.

今回は–alter=‘change column pad new_pad char(60),add column pad char(60)’という風に、列名の変更と変更前の列の再作成を行なうために実行の際には–no-check-alterを付与した。こんな感じでオプションに引数を与えておけばOK。

./pt-online-schema-change --alter='change column pad new_pad char(60),add column pad char(60)' h=sbtest.cfscsg6f7tbd.us-east-1.rds.amazonaws.com,P=3306,D=db_sbtest,t=sbtest,u=sbtest_user,p=sbtest_passwd --statistics --recursion-method processlist --print --execute --no-check-alter

生のalter文との処理に比べて、さすがに時間はかかる。ただ、CPU利用率は抑えられるし、何よりオンラインでalter文を発行できるメリットは大きい。とはいえ、MySQL5.6からalterはオンラインに対応するようにはなっているので、MySQL5.5以前のバージョンを使っている場合は利用を検討する価値はあるように思う。

おまけ

cpanmでDBD::mysqlをインストールしようとしたら、以下の様なエラーが出て失敗した。

t/10connect.t ........................ Bailout called.  Further testing stopped:  ERROR: Access denied for user 'root'@'localhost' (using password: NO)

ログを調べると以下のように出ていた。

You can also optionally set the user to run 'make test' with:

perl Makefile.PL --testuser=username

なので、rootでlocalhostのmysqlにアクセスできるようにするための設定を行ってあげればOK。

$ sudo perl Makefile.PL --testuser=root --testpassword=root_password
Password:
I will use the following settings for compiling and testing:

  cflags        (mysql_config ) = -I/usr/local/Cellar/mysql/5.6.10/include  -Os -g -fno-strict-aliasing
  embedded      (mysql_config ) =
  ldflags       (mysql_config ) =
  libs          (mysql_config ) = -L/usr/local/Cellar/mysql/5.6.10/lib -lmysqlclient
  mysql_config  (guessed      ) = mysql_config
  nocatchstderr (default      ) = 0
  nofoundrows   (default      ) = 0
  ssl           (guessed      ) = 0
  testdb        (default      ) = test
  testhost      (default      ) =
  testpassword  (User's choice) = root_password
  testport      (default      ) =
  testsocket    (default      ) =
  testuser      (User's choice) = root

To change these settings, see 'perl Makefile.PL --help' and
'perldoc DBD::mysql::INSTALL'.

Using DBI 1.622 (for perl 5.016002 on darwin-thread-multi-2level) installed in /System/Library/Perl/Extras/5.16/darwin-thread-multi-2level/auto/DBI/
Writing Makefile for DBD::mysql
Writing MYMETA.yml and MYMETA.json

あとはmake && make test && sudo make installしておけばOK。