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
  1. autocommit=0  
  2. innodb_flush_log_at_trx_commit=0  
  3. innodb_support_xa=0  
  4. character-set-client-handshake=0  
  5. character_set_client=utf8  
  6. character_set_connection=utf8  
  7. character_set_database=utf8  
  8. character_set_filesystem=utf8  
  9. character_set_results=utf8  
  10. character_set_server=utf8  
・レプリケーション向けRDS Parameter Group
  1. innodb_flush_log_at_trx_commit=0  
  2. character-set-client-handshake=0  
  3. character_set_client=utf8  
  4. character_set_connection=utf8  
  5. character_set_database=utf8  
  6. character_set_filesystem=utf8  
  7. character_set_results=utf8  
  8. character_set_server=utf8  
・本番運用向けRDS Parameter Group
  1. innodb_flush_log_at_trx_commit=2  
  2. character-set-client-handshake=0  
  3. character_set_client=utf8  
  4. character_set_connection=utf8  
  5. character_set_database=utf8  
  6. character_set_filesystem=utf8  
  7. character_set_results=utf8  
  8. 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
  1. [mysqld]  
  2. log-bin=mysql-bin  
  3. expire_logs_days=7  

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

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

6.既存DBから、フルダンプをファイルに書き出しつつRDSに投入
(投入速度をあげるために、ユニークキー、外部キーのチェックをOFFにしている)
  1. $ (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のファイル名とポジションを確認
  1. $ grep -m 1 MASTER_LOG /mnt/storage/dump.sql   
  2. -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000242'MASTER_LOG_POS=24812749;  

8.RDSでレプリケーションの設定
  1. CALL mysql.rds_set_external_master('10.xxx.xxx.xxx',3306,'replicator','password','mysql-bin.000242',24812749,0);  
  2. Query OK, 0 rows affected (0.11 sec)  
  3.   
  4. CALL mysql.rds_start_replication;  
  5.   
  6. +-------------------------+  
  7. | Message    |  
  8. +-------------------------+  
  9. | Slave running normally. |  
  10. +-------------------------+  
  11. 1 row in set (1.05 sec)  
  12.   
  13. Query OK, 0 rows affected (1.05 sec)  

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

10.念のためマスター側(非RDS)の方でもプロセスを確認
  1. mysql> show processlist;  
  2. | 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.待っている間にレプリケーション中にエラーが起きた場合は、内容を確認してスキップするなどして対処する
  1. mysql> CALL mysql.rds_skip_repl_error;  
  2. +-------------------------------------+  
  3. | Message         |  
  4. +-------------------------------------+  
  5. | Statement in error has been skipped |  
  6. +-------------------------------------+  
  7. 1 row in set (0.04 sec)  
  8.   
  9. +---------------------------+  
  10. | Message      |  
  11. +---------------------------+  
  12. | Slave is running normally |  
  13. +---------------------------+  
  14. 1 row in set (2.05 sec)  
  15.   
  16. Query OK, 0 rows affected (2.05 sec)  

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

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

14.RDSをマスターモードに切り替え
  1. mysql> CALL mysql.rds_stop_replication;  
  2. +---------------------------+  
  3. | Message      |  
  4. +---------------------------+  
  5. | Slave is down or disabled |  
  6. +---------------------------+  
  7. 1 row in set (1.08 sec)  
  8.   
  9. Query OK, 0 rows affected (1.08 sec)  
  10.   
  11. mysql> CALL mysql.rds_reset_external_master;  
  12. +----------------------+  
  13. | message        |  
  14. +----------------------+  
  15. | Slave has been reset |  
  16. +----------------------+  
  17. 1 row in set (0.18 sec)  
  18.   
  19. Query OK, 0 rows affected (0.18 sec)  

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

0 件のコメント:

コメントを投稿