セクションナイン の 吉田真吾(@yoshidashingo)です。
DB無停止移行は人類の夢
暗号化していないRDS MySQLから暗号化済みのAuroraに移行したいけど、スナップショットの復元でもAurora Read Replicaのマスター昇格でも一発ではリソース暗号化ができませんが、そんなときに便利なのがDatabase Migration Service(DMS)です。
DMSを使えばどちらかがリソース暗号化されたデータベースであってもフルデータロード+継続レプリケーションができます。
今回はDMSからの接続に必要な移行元のbinlogのフォーマットを変えずに(DMSでレプリケーションできないDBが移行元であっても)レプリケーションするために、間にAurora Replicaを用いて実装してみます。
利用する特徴
- Aurora Read Replicaはbinlog_formatがROWでないRDS MySQLから簡単に継続レプリケーションできる
- DMSは非暗号化<->暗号化データベース間の読み書きをサポートしている
- DMSのターゲットデータベースのロジカルレプリケーションはターゲットへの書き込みもできる
少しAWSに覚えのある方であればこの特徴だけでどうやればよいかわかると思うので、後は読まなくても大丈夫です、これを組み合せることで無停止で移行します。
手順
説明用の3種類のデータベースインスタンス名は以下のような名前になっています。
- 移行元データベース(MySQL) mydbinstance
- 中間データベース(DMSのソースデータベース: Aurora) mydbinstance2
- 移行先データベース(DMSのターゲットデータベース: Aurora) mydbinstance3
移行元データベース(MySQL)
移行元のRDS MySQLではデフォルトのパラメータグループを作成している想定です。
バックアップは1日以上(今回の場合は2日)設定されているものとします。ストレージ暗号化はされていないので、この状態からでは暗号化済みのAuroraに一発で移行することはできません。
中間データベース(Aurora Read Replica)
CDCを利用した継続レプリケーションを行うために、移行元のRDS MySQLのAurora Read Replicaを作成します。
Auroraのbinlogからレプリケーションを有効にするためにDBクラスターパラメータグループの設定変更をします。デフォルトのものは設定変更ができないので、あらかじめ新規にDBクラスターパラメーターグループを作成して以下の値を変更しておき、Aurora Read Replicaの作成時にこれを適用してインスタンスを作成します。
- binlog_checksum NONE
- binlog_format ROW
また、mysqlクライアントで接続し、binlogの保持期間の変更を行っておきます。エラーでレプリケーションが止まっても十分に対応できる程度の時間にしておきましょう。今回は12時間に設定しておきました。
mysql> CALL mysql.rds_set_configuration('binlog retention hours', 12);
移行先データベース(暗号化済みAurora)
移行先は(せっかくの機会なので)暗号化しときましょう。デフォルトのDBクラスターパラメータグループだと後で設定を返るときに不便ですが今回は無視します。こちらのbinlogは今回不要です。
DMS
適当なサイズでDMSインスタンスを作っておきます。
ちなみにこの状態だとMySQLとAurora Read Replicaのテーブルにはデータが入ってますが、ターゲットにはデータが入っていない状態になります(上から1号機/2号機/3号機)
ソース/ターゲットデータベースに接続する
タスクを作成して実行する
対象のスキーマを指定してマイグレーションタスクを投入します。マイグレーションタイプには初期データのフルロードと継続レプリケーションを選択しましょう。
このタスクを実行すると、フルデータロードされてターゲットにもデータが同期されます。
このタイミング、あるいはフルデータロード後に一時停止しておいて一度「Analyze Table」しておきましょう。
継続レプリされているか確認する
もう一行挿入して継続レプリされているか確認しましょう。
アプリ切替
移行元ではなくターゲットに直接データを書き込んでみましょう。
ターゲットにのみデータが書き込まれました。
移行元にデータを書き込む
この状態で一部のトランザクションが移行元側に入ってしまっても、ターゲットにまで伝搬するので問題ありません。
よって、複数のアプリの切替が必要な場合でも、このレプリケーションが継続レプリケーションを行い始めた後であれば、それぞれ任意のタイミングで切替が可能になりうるということが分かります。
まとめ
手順を見れば分かるとおり、同一レコードへのトランザクションが移行元/移行先に別々に入ってしまう場合や、Auto Increment属性が付与されているテーブルに移行元/移行先に別々に入ってしまう場合などについての考慮は必要になりますが、そういう条件が発生しえない場面においては、レプリケーションを切り離すタイミングとアプリの切替を同期する必要がなくなるのは嬉しい方法ではないかと思います。
また、統計情報の再作成のためのAnalyze Tableのタイミングについては今回適当に継続レプリケーション中に行いましたが、実際はターゲットデータベースにかかるワークロードを考慮したタイミングを精査しておく必要があると思います。実際DMSではフルデータロード後で継続レプリケーションを開始する直前に一時停止させることができるので、そのタイミングでAnalyzeさせることも可能です。
また、データベースの移行・切替は非常にセンシティブな作業ですので、実際に作業する時は事前に十分な検証したうえで実行しましょう。