2013-09-08

非RDSのMySQLをRDSへ短時間メンテナンスで移行する方法

非RDSのMySQLをRDSに移行する方法としてまず思い浮かぶのが

  1. 移行先のRDSを用意
  2. メンテナンスを入れて非RDSへの書き込みがなくなるようにする
  3. 非RDSからmysqldump
  4. mysqldumpしたデータをRDSへ投入
  5. 利用するDBをRDSに切り替え
  6. 動作確認
  7. メンテナンス解除

といった具合ですが、データベースに格納されているデータが大きいとメンテナンス時間は長時間に及びます
mysqldumpした後のデータサイズが約40GBの状態で試算してみると
mysqldumpに1時間、投入に3時間ぐらいは掛かりそうな雰囲気でした
これだけ長時間になるとサービスに与える影響が大きいなぁということで、いろいろと調べていてたどり着いたのがこの方法

  1. 非RDSからmysqldump
  2. 移行先のRDSを用意
  3. mysqldumpしたデータをRDSへ投入
  4. RDSを非RDSをマスターとしてレプリケーションするように設定
  5. メンテナンスを入れて非RDSへの書き込みがなくなるようにする
  6. RDSのレプリケーション設定を解除して、マスターモードで稼働するよう設定
  7. 利用するDBをRDSに切り替え
  8. 動作確認
  9. メンテナンス解除
※ただし、RDSを非RDSからレプリケーションさせるには5.5系だと5.5.33以降、5.6系だと5.6.13以降である必要あり

この方法ならば、長時間に及ぶ作業はメンテナンス前に実施してしまい
メンテナンス中に行う作業は短時間の作業のみにできます
1時間もあれば十分な感じです

具体的な方法は次の通り

1.RDS Parameter Groupを3つ準備(デフォルトから変更するパラメータのみ記載)
・データ投入向け RDS Parameter Group
autocommit=0
innodb_flush_log_at_trx_commit=0
innodb_support_xa=0
character-set-client-handshake=0
character_set_client=utf8
character_set_connection=utf8
character_set_database=utf8
character_set_filesystem=utf8
character_set_results=utf8
character_set_server=utf8
・レプリケーション向けRDS Parameter Group
innodb_flush_log_at_trx_commit=0
character-set-client-handshake=0
character_set_client=utf8
character_set_connection=utf8
character_set_database=utf8
character_set_filesystem=utf8
character_set_results=utf8
character_set_server=utf8
・本番運用向けRDS Parameter Group
innodb_flush_log_at_trx_commit=2
character-set-client-handshake=0
character_set_client=utf8
character_set_connection=utf8
character_set_database=utf8
character_set_filesystem=utf8
character_set_results=utf8
character_set_server=utf8

2.RDS起動
5.5系なら5.5.33以降、5.6系なら5.6.13以降を選択
データ投入向けRDS Parameter Groupを選択
binlogを出力しないよう設定(Enabled Automatic BackupsをNoに設定)
Multi AZ=No

3.非RDSでmysql binlogが出力されるよう設定
/etc/my.cnfに以下を設定してrestart
[mysqld]
log-bin=mysql-bin
expire_logs_days=7

4.非RDSでレプリケーション用ユーザ作成
mysql> grant all on *.* to replicator identified by 'password';
Query OK, 0 rows affected (0.09 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.04 sec)

5.非RDSの3306ポートにRDSから接続できるようFWやセキュリティグループを設定

6.既存DBから、フルダンプをファイルに書き出しつつRDSに投入
(投入速度をあげるために、ユニークキー、外部キーのチェックをOFFにしている)
$ (echo "SET unique_checks=0;SET foreign_key_checks=0;"; mysqldump --order-by-primary --add-drop-table --add-locks --master-data=2 --quick --all-databases -udbuser -p) | tee /mnt/storage/dump.sql | mysql -f -urdbuser -p -h xxx.yyy.ap-northeast-1.rds.amazonaws.com database_name

待つこと数時間…

7.書き出したファイルからbinlogのファイル名とポジションを確認
$ grep -m 1 MASTER_LOG /mnt/storage/dump.sql 
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000242', MASTER_LOG_POS=24812749;

8.RDSでレプリケーションの設定
CALL mysql.rds_set_external_master('10.xxx.xxx.xxx',3306,'replicator','password','mysql-bin.000242',24812749,0);
Query OK, 0 rows affected (0.11 sec)

CALL mysql.rds_start_replication;

+-------------------------+
| Message    |
+-------------------------+
| Slave running normally. |
+-------------------------+
1 row in set (1.05 sec)

Query OK, 0 rows affected (1.05 sec)

9.RDSでレプリケーションステータスの確認
mysql> show slave status \G
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 11069

10.念のためマスター側(非RDS)の方でもプロセスを確認
mysql> show processlist;
| 123 | replicator | ip-10-xxx-xxx-xxx.ap-northeast-1.compute.internal:57028 | NULL    | Binlog Dump |   77 | Master has sent all binlog to slave; waiting for binlog to be updated | NULL  
RDSから接続が来ていますね

このあたりが確認できれば接続はOK
あとは、マスターDBからの遅延時間
Seconds_Behind_Master: 11069
が0になってくれるまで待機


11.待っている間にレプリケーション中にエラーが起きた場合は、内容を確認してスキップするなどして対処する
mysql> CALL mysql.rds_skip_repl_error;
+-------------------------------------+
| Message         |
+-------------------------------------+
| Statement in error has been skipped |
+-------------------------------------+
1 row in set (0.04 sec)

+---------------------------+
| Message      |
+---------------------------+
| Slave is running normally |
+---------------------------+
1 row in set (2.05 sec)

Query OK, 0 rows affected (2.05 sec)

12.Enabled Automatic BackupsをYesに設定
Modifyして1日以上に設定

13.マスター稼働用のパラメータグループに変更

14.RDSをマスターモードに切り替え
mysql> CALL mysql.rds_stop_replication;
+---------------------------+
| Message      |
+---------------------------+
| Slave is down or disabled |
+---------------------------+
1 row in set (1.08 sec)

Query OK, 0 rows affected (1.08 sec)

mysql> CALL mysql.rds_reset_external_master;
+----------------------+
| message        |
+----------------------+
| Slave has been reset |
+----------------------+
1 row in set (0.18 sec)

Query OK, 0 rows affected (0.18 sec)

ここまで来たら、あとは動作確認して終了ヾ(*・∀・)ノ"

0 件のコメント:

コメントを投稿