ちゃんるいすのブログ

オタクエンジニアの雑記

AWS DMS を使ってプライベートクラウドの巨大な MySQL を Aurora MySQL へ移行してみた


今までプライベートクラウドで動いてたサービスが、データセンターの閉鎖に伴いどこかに移設しないといけない物語に AWS DMS を使ったので覚書として書いておく。
DB は 1.5TB の 45 億レコードとそれなりに大きいけどメンテ時間は動作確認を除いて 30 分ぐらいで終わった。

ちなみに、SCT は使ってない(使えなかった)のでここでは触れない。

AWS DMS

aws.amazon.com

AWS DMS の説明は公式を見てください。
今回はプライベートクラウドにある MySQL5.6 -> Aurora MySQL 5.6 互換への移行をしたよ

必要なこと

AWS DMS を使うにあたっていくつか事前準備がいる。

f:id:rarirureluis:20190911165923p:plain

いくつかのパラメータは SET GLOBAL で適用できるので良いけど、現在のセッションには適用されないのでアプリケーションの再起動とかは必要。

DMS の制限事項

AWS DMS は、移行の実行に必要なターゲットスキーマオブジェクトを作成します。ただし、AWS DMS は最小限のアプローチを採用するため、データの効率的な移行に必要なオブジェクトのみ作成します。つまり、AWS DMS は、テーブル、プライマリキー、場合によっては一意のインデックスを作成しますが、効率的にソースからデータを移行するために必要ではない他のオブジェクトは作成されません。たとえば、セカンダリインデックス、非プライマリキーの制約、データデフォルトは作成されません。

docs.aws.amazon.com

セカンダリインデックスをつけたまま移行したい

1. mysqldump でテーブルの定義だけをダンプして、ターゲットへインポートする。
2. タスクの設定を変更する

f:id:rarirureluis:20190911170648p:plain

デフォルトのタスクの設定は DROP TABLE IF EXISTS がついてる!TRUNCATE にすれば :ok:

お使いの環境にもよりますが、セカンダリインデックス無しでフルロードは12時間程度に終わるのに対して、セカンダリインデックス有りでフルロードすると2日かからないぐらいかかる。
インサートされる度にインデックスのソートが走るのでこれが重い。
できるなら、mysqldiff とかで ADD INDEX のみの差分 DDL を取っておいて、フルロード完了後に流すのが1番早いと思う。

この辺は前職の先輩に教えてもらった。大感謝。


2つのソースを1つのターゲットにすることは可能か?

できる

レプリケーションインスタンスサイズの決め方

CloudWatch ログを有効化にする。
とりあえずタスクを走らせる → メモリとか CPU がパツってたらレプリケーションインスタンスをスケールアップする。
ターゲットのインスタンスサイズも同様に、メトリクスを見てうまいこと決めていくのが良いと思う。適当。

Direct Connect とか、AWS VPN は絶対に必要か?

いらない。ちょっと前からレプリケーションインスタンスに GIP が付与されるようになった。

SSL は使えるか?

使える。
ソースの MySQL のバージョンが低い(OpenSSH が古い)と、DH鍵のビット数が少ないため、DMS 側から切断されて使えない -> error:14082174:SSL routines:ssl3_check_cert_and_algorithm:dh key too small
が、ソースの MySQLssl-cipher = AES128-SHA と明示的に DHE を使わない暗号スイートにすれば強度は弱いが SSL を使えないことはない。

実際に切り替えるとき

ソース

メンテに振った後、絶対に更新させないという意気込みを伝える。

mysql> FLUSH TABLES WITH READ LOCK;
mysql> SET GLOBAL read_only = ON;
ターゲット

ソース側でポジションが変わらないことを確認したあとに、DMS のタスクを停止する。

これだけで DB の移行は終わり。
神!!!!!!!!!!!!!!!!!!!!!!!!!!!!