search
LoginSignup
10

More than 5 years have passed since last update.

posted at

updated at

Organization

複数のRDSから1台のMySQL on EC2にレプリケーションをする方法

自分的メモも兼ねて

構成

マイクロサービスの様な、複数のマスターRDSを持つ様な構成で分析用などにslaveを持ちたい場合に、それぞれのRDSについてリードレプリカを作成すると、マスターの個数分だけリードレプリカを作成する必要があり経済的な問題が生じる。
また、分析的な業務ではデータベースを跨いでJOINしたかったりするかもしれないため、一つのMySQLに複数のdatabaseのレプリケーションを受けたい。

マルチソースレプリケーション

MySQL5.7から導入された、database毎にレプリケーションの設定が出来る機能。
https://dev.mysql.com/doc/refman/5.7/en/replication-multi-source.html

作業

Read Replicaを作成する

RDSにはFLUSH TABLES WITH READ LOCK権限が無いため、マスターから以下のようなコマンドでdumpを取得する事が出来ない。
(--master-dataは、CHANGE MASTER分をdumpの最後に付けるオプションだが、これをする為にはFLUSH TABLEしてポジションを取得しないといけない。)

$ mysqldump -h example.ap-northeast-1.rds.amazonaws.com -u user -p --single-transaction --master-data --databases sample > sample.sql
Enter password: 
mysqldump: Couldn't execute 'FLUSH TABLES WITH READ LOCK': Access denied for user 'user'@'%' (using password: YES) (1045)

このため、まずはRead Replicaを作成し、そこからデータをダンプした後、マスターに繫ぐという事をする。

Read Replicaのレプリケーションを止めてポジションを記録する

Read Replicaが作成出来たら、以下のコマンドでレプリケーションを停止させる。これは、RDSでデフォルトで用意されているプロシージャ。

call mysql.rds_stop_replication;

レプリケーションが止まったら、SHOW SLAVE STATUSでいまのポジションを記録しておく。必要なのはこの二つ。マスターのどのbinlogを読んでいるか、そのbinlogのどこまで読んだか。

Master_Log_File: mysql-bin-changelog.090689
Read_Master_Log_Pos: 23395

Read Replicaからdumpを取得し、MySQLに流し込む

レプリを止めたらその状態のデータをmysqldumpで取得して、今回新しくスレーブにしたいMySQLに流し込む。

dumpを取得し、

mysqldump -hexample-readreplica.ap-northeast-1.rds.amazonaws.com -u user -p --single-transaction --databases sample > sample.sql

流し込み。

cat sample.sql | mysql -uroot -p

MySQL側でCHANGE MASTERし、レプリを開始する

流し込みが終わったら、対象のMySQLサーバーにログインしてCHANGE MASTERを打つ。このとき、先ほど記録していたbinlogの値を使用する。
今回はマルチソースでレプリケーションしたいので、FOR CHANNELで固有のチャンネル名を指定する。

mysql> CHANGE MASTER TO
  MASTER_HOST='xxx.xxx.xxx.xxx',
  MASTER_USER='repl',
  MASTER_PASSWORD='XXXXXXXXXXX',
  MASTER_LOG_FILE='mysql-bin-changelog.090689',
  MASTER_LOG_POS=23395 FOR CHANNEL 'sample';

エラーが出なければ、レプリを再開。この時にもCHANNEL指定。

mysql> START SLAVE FOR CHANNEL 'sample';

確認。

mysql> SHOW SLAVE STATUS FOR CHANNEL 'sample';

ここまで問題なければ一つのRDSに関しては終了。
引き続き他のRDSに関しても同じ作業を繰り返せばOK(ただし、CHANNEL名は全て固有の値にする事)。

(補足) binlogの保持期間について

RDSのbinlogはデフォルトでは必要なくなったら消されてしまうため、ダンプやリストアしている間に消えてしまう事がある。
以下の様に保持期間を伸ばしておくと良い。ちなみに、これもRDSが用意しているプロシージャ。

mysql> call mysql.rds_set_configuration('binlog retention hours', 24);

現在の設定値の確認方法。

mysql> call mysql.rds_show_configuration;

まとめ

マルチソースレプリケーションが便利すぎた。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
10