AWSのDMSを使ってデータを移行してみた

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
あっちからこっちへ

この記事を三行にまとめると

MySQLからAuroraに乗り換えました
1時間かからずに移行できたのはすごいなと思いました
テーブルの構造を変更したい時にも活用できんじゃね?
先日仕事で運用しているサービスのデータベースをRDSのMySQLからAuroraに乗り換えました。

実はAuroraに乗り換えたいという思いは3年くらい前からずっとあったんですが、データ量が多すぎて「もはやAuroraに乗り換えるのは無理じゃね?」とほぼあきらめてたんですよ。でもAWSにはDatabase Migration Serviceというなかなか便利なサービスがあることに気づきまして……こいつを使ったら大量のデータ移行を伴うDBの乗り換えもわりとスムーズにできたので、今日はこのDMSの使い方や移行にかかった時間などをお話したいと思います。

DMSでデータを移行するには以下の作業が必要になります。

新しいデータベースの作成と注意点
レプリケーションインスタンスの作成
エンドポイントの作成
移行タスクの作成

順番に見ていきやしょう。



新しいデータベースの作成と注意点

まずは移行先となる新しいデータベースの作成です。今回でいうとAuroraの作成ですね。これに関しては今回の本題ではないので作成方法については割愛します。

注意なのですが、自動バックアップを無効にしている場合もエラーが出るようです。本番運用するデータベースならバックアップを無効にすることはないと思うのですが、テスト用のデータベースでDMSを試す場合、テスト用だからバックアップはいらねーだろとか思ってバックアップの保持期間を0日にしてしまうとデータ移行の際に以下のようなエラーが出るので、テスト用であってもバックアップの保持期間は1日以上にしといてください。

Last Error Failed in resolving configuration. Task error notification received from subtask 0, thread 0 [reptask/replicationtask.c:2822] [1020418] Error Code [10001] : Binary Logging must be enabled for MySQL server; Errors in MySQL server binary logging configuration. Follow all prerequisites for 'MySQL as a source in DMS' from https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Source.MySQL.html or'MySQL as a target in DMS' from https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Target.MySQL.html ; Failed while preparing stream component 'st_0_sample-db'.; Cannot initialize subtask; Stream component 'st_0_sample-db' terminated [reptask/replicationtask.c:2829] [1020418] Stop Reason FATAL_ERROR Error Level FATAL

僕も最初0にして「何でさ?」ってなった

もしバックアップは有効なのにこのエラーが出るって場合は、エラーの中にあるこのURLにアクセスするとデータ移行の際に必要となる条件みたいなのが書いてあるので、そこから原因の特定ができるかもです。

https://docs.aws.amazon.com/ja_jp/dms/latest/userguide/CHAP_Source.MySQL.html



レプリケーションインスタンスの作成

続いてレプリケーションインスタンスの作成です。といっても別に難しいことはありません。設定項目を順番に埋めていけばOKです。

レプリケーションインスタンス

個人的に引っかかったのはインスタンスクラスですかね。とりあえず安いインスタンスでテストしてみようと思って最初はt3.microに設定したんですが、メモリ不足か何かでデータの移行ができませんでした。なので多少大きめのインスタンスにしておいた方が良いと思います。

エンジンバージョンはとりあえず最新にしときゃ問題ないと思います。ストレージも適当に50GBとか100GBとかにしておけば大丈夫でしょう。

マルチAZはなしでも良いんじゃないかなと思います。よほどデータの移行が急務とかでなければ失敗したら最初からやり直せば良いので、耐障害性を重視するかは要検討って感じで。



エンドポイントの作成

エンドポイントは「ソースエンドポイント」と「ターゲットエンドポイント」の2つ作成します。ソースエンドポイントは移行元のデータベースのエンドポイント、ターゲットエンドポイントは移行先のデータベースのエンドポイントです。

これも特に難しいことはないです。それぞれのデータベースの接続情報を入力するだけです。

エンドポイントの作成

移行先がAuroraの場合は書き込み用のデータベースをターゲットエンドポイントに設定すればOKです。作成画面の下の方に接続テストというのがありますが、これでテストを実行して「Successful」と出たらデータベースへの接続が正常に行えていることになります。接続情報が間違っていなければエラーは出ないと思うので、たぶんここはスムーズに作業完了できると思います。

接続テスト



移行タスクの作成

ではいよいよ移行タスクの作成です。

タスクの設定も特に難しいことはなく、先ほど作成したレプリケーションインスタンスや各エンドポイントを選択すれば良いのですが、設定内容によっては下の画像のように「バイナリログを有効にしてください」と言われることがあります。

タスクの作成

この場合はRDSのパラメータグループの「binlog_format」をROWにしておく必要があります。

バイナリログの設定

もしかしたら実際にデータ移行を行う際に「ターゲットエンドポイントの方もバイナリログをROWにしろよ」的なエラーが出るかもしれませんが、その時はターゲット側のデータベースに付与しているパラメータグループのbinlog_formatもROWにしてください。ちなみにAuroraの場合はパラメータグループが通常のパラメータグループとDBクラスターのパラメータグループの二つあるのですが、binlog_formatがあるのはクラスターの方のパラメータグループです。

それから移行タイプについてですが、「既存のデータを移行して、継続的な変更をレプリケートする」にしておくと、移行が終わった後も移行元のデータベースに更新がかかった場合に移行先の方にもその更新を同期してくれます。本番運用しているサービスで、サービスを止めずに移行したい場合はこれを選ぶと良いかもしれません。

続いて編集モードですが、基本的には初期設定のまま何もいじらなくても大丈夫だと思います。

今回は先にテーブルを作っておきたかったのでこうしました

僕の場合は「ターゲットテーブルの作成モード」というところだけ「何もしない」に変更しました(デフォルトはターゲット上のテーブルを削除になっている)。「何もしない」にした場合はデータだけを移行する動きになります。テーブルの作成も一緒に行いたい場合は「ターゲット上のテーブルを削除」のままで良いでしょう。

テーブルマッピングは移行するデータベースをスキーマやテーブルを選択します。

テーブルマッピング

デフォルトだとスキーマもテーブルもワイルドカードになっているんですが、この設定だと移行元にある全てのデータを移行します。通常、RDSやAuroraを作成すると「information_schema」や「mysql」などのデータベースが作られていると思うんですが、スキーマをワイルドカードにするとこれらのデータもまとめて移行しようとするので、スキーマは移行させたいデータベースだけにしといた方が良いと思います。「information_schema」や「mysql」は移行する必要がないし、むしろmysqlなんかはエラーが出て移行できないと思うので。



タスクが無事に作成できたらあとは移行を開始するだけです。移行にかかる時間はデータの量によって変わってきますが、結構なデータ量であってもわりと早く完了します。

僕の場合はこんな感じでした。

テーブル数・・・113
レコード数・・・約4700万
データ容量・・・約11GB
かかった時間・・・約35分

4700万行のデータが1時間かからずに移行できたのはすごいなと思いました。自分でSQLのダンプファイルを作って手動で移行……みたいなことやってたらこんなに早くは終わらなかったと思います。






ちょい説明が急ぎ足になってしまったかもしれませんが、こんな感じで大量のデータ移行もできるぞという話でした。

個人的にDMSが良いなと思ったのは、単純にデータを移行できる点もそうなんですけど、「大量のデータが入ってるテーブルの構造を変更したい時にも活用できんじゃね?」っていう点です。

今回実際にやったことなんですけど、いくつかのテーブルのプライマリーキーをintからbigintに変えたいなと思いまして、でも数百万とか数千万件のデータが入ってるテーブルにALTER TABLEを使うと負荷がやべーことになるんですよ。というか先日それをやってしまいまして……本番稼働しているデータベースのテーブルにALTER TABLEをかけたらデータベースにつながらなくなってしまいました。幸い2分程度で再びつながるようになったのでそこまで致命的にやばいことにはならなかったのですが、もうこのテーブルにはALTER TABLEは使えないのかーと思っていたところに、上手いこと今回の以降の話が重なりまして……「移行先のデータベースに先にbigintに変更したテーブルを作っておけば万事解決やん!」となったわけですよ。先ほどテーブル作成モードを「何もしない」にしたのはこの設定変更を行いたかったからです。

カラムを削除したりするとデータの整合性が取れなくてエラーになってしまうかもしれませんが、型の変換くらいだったらこういう対処法もあるのかなと……まあALTER TABLEが必要なたびに新しいデータベースを作ってデータを移行するのもどうかとは思いますが、たまにだったら悪くない選択肢なのかもしれません。
 もしかしたら何か関連しているかも? 
 質問や感想などお気軽にコメントしてください