AWS DMSでデータ移行を試してみた

こんにちは。入社して半年が経ちました、kohachanです。
最近AWS DMSを使ってデータ移行を検証する機会があったので、今回はDMSで移行を行う際の設定ポイントと実際の手順をまとめてみたいと思います。
前提条件
今回の検証は、以下の条件で行いました。
MySQLの同種間での移行になるので、そこまで複雑なケースではありません。
- Amazon RDS for MySQL同士の移行(移行元、移行先どちらもAmazon RDSでMySQLエンジンを使用する)
- 移行元のMySQLのバージョンは5.7系で、移行先のバージョンは8.0系
- 継続的レプリケーション(データ変更を継続的に移行先のデータベースに移行する)が行われるようにする
※継続的レプリケーションとは、一度データ移行した後も継続的にデータ変更を移行先に同期してくれるDMSの機能です。サービス停止の時間をあまり取れない場合には、継続的レプリケーションは有効な手段かと思います。
設定のポイント
設定にあたってポイントになる部分は以下になります。
移行元RDSのバイナリログを有効にする
継続的レプリケーション(CDC)を行う場合は、パラメータグループの設定を変更し、バイナリログを有効にする必要があります。
また、RDS for MySQLでバイナリログを有効にするには、自動バックアップも有効にする必要があります。
ただし、継続的レプリケーションを使用しない場合には、上記の設定は不要です。
公式ドキュメントとしては、以下のページに記載があります。
移行元RDSの設定について: https://docs.aws.amazon.com/ja_jp/dms/latest/userguide/CHAP_Source.MySQL.html#CHAP_Source.MySQL.AmazonManaged
継続的レプリケーションについて: https://docs.aws.amazon.com/ja_jp/dms/latest/userguide/CHAP_Task.CDC.html
移行先RDSの一部設定を無効にする
移行先のRDSでは、AWS DMSでの移行中は以下の設定を無効化することがベストプラクティスとなっています。
そのため、移行中はこちらの設定は無効化しておきましょう。
- マルチAZ
- 自動バックアップ
- データベース固有のログ (バイナリ、一般、監査など)
こちらは、AWSの情報センターに記載がありました。
https://repost.aws/ja/knowledge-center/dms-mysql-source-mysql-target
mysqldumpでテーブル定義を事前にインポートする
同種間移行の場合、mysqldumpなどのネイティブツールで移行先のRDSにテーブル定義を事前にインポートしておくことが推奨されています。
そのため、移行前にmysqldumpでテーブル定義のみ事前に取得しておきます。
こちらの情報も、一つ前で紹介しているドキュメントに記載されています。
実際の手順
それでは、実際に環境を構築して試してみたいと思います。
移行元のRDSインスタンスと移行先のRDSインスタンスを作成し、DMSで移行に必要な設定をしていきます。
構築後は、実際にデータの移行を実施して動作確認を行います。
セキュリティグループの作成
最初に、DMSレプリケーションインスタンス、RDSインスタンスで使用するセキュリティグループを作成しておきます。
まず、DMS用セキュリティグループを作成します。
特にインバウンドルールを追加する必要はありません。

次に、RDS用セキュリティグループを作成します。
DMSレプリケーションインスタンスからのアクセスを許可するルールを追加します。(画像中では踏み台用EC2インスタンスからのアクセス許可も入れていますが、こちらは必要に応じて変更してください)

移行元(ソース)RDSの作成
移行元のRDSを作成します。
まず、パラメータの変更が必要になるため、以下の設定でカスタムパラメータグループを作成します。

さらに、継続的レプリケーション(CDC)の実行に必要なバイナリログを有効化するために、以下の設定を変更します。
項目 | 設定値 |
---|---|
binlog_checksum | NONE |
binlog_format | ROW |
binlog_row_image | full |

次にRDSインスタンスを作成します。
以下のようにそれぞれの項目を設定します。
その他は任意の設定で大丈夫です。
項目 | 設定値 |
---|---|
エンジンのオプション | MySQL |
エンジンバージョン | MySQL 5.7.44 |
VPCセキュリティグループ | RDS-SG(前述で作成したもの) |
DB パラメータグループ | 前述で作成したカスタムパラメータグループ |
最初のデータベース名 | テスト用の任意の名前のDB名を入れる(今回は「test」で作成) |
自動バックアップを有効にします | チェックあり |





移行元RDSのバイナリログ保持期間を変更
バイナリログの保持期間も変更する必要があります。
対象RDSに接続後、以下のようなコマンドを実行します。
# 現在のバイナリログ保持期間を確認
mysql> call mysql.rds_show_configuration;
# 保持期間を24時間に変更
mysql> call mysql.rds_set_configuration('binlog retention hours', 24);
テスト用データの作成
以下のSQLでテーブルスキーマの定義、テストデータの投入をします。
CREATE TABLE test.tb_1 (
ID INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255),
nickname VARCHAR(255),
registered DATETIME
);
INSERT INTO test.tb_1 (name, nickname, registered) VALUES
('John Doe', 'JD', '2023-01-01 12:00:00'),
('Jane Smith', 'JS', '2023-02-15 08:30:00'),
('Bob Johnson', 'BJ', '2023-03-30 18:45:00');
テーブルにデータが入っていることが確認できます。
mysql> SELECT * FROM test.tb_1;
+----+-------------+----------+---------------------+
| ID | name | nickname | registered |
+----+-------------+----------+---------------------+
| 1 | John Doe | JD | 2023-01-01 12:00:00 |
| 2 | Jane Smith | JS | 2023-02-15 08:30:00 |
| 3 | Bob Johnson | BJ | 2023-03-30 18:45:00 |
+----+-------------+----------+---------------------+
移行先(ターゲット)RDSの作成
以下のようにそれぞれの項目を設定して、移行先のRDSインスタンスを作成します。
その他は任意の設定で大丈夫です。
項目 | 設定値 |
---|---|
エンジンのオプション | MySQL |
エンジンバージョン | MySQL 8.0.33 |
デプロイオプション | 単一 DB インスタンス |
VPCセキュリティグループ | RDS-SG(前述で作成したもの) |
最初のデータベース名 | 移行元RDSで作成したDB名を入れる(今回は「test」で作成) |
自動バックアップを有効にします | チェックなし |
ログのエクスポート | 全てチェックなし |
前述の設定ポイントで示した通りですが、以下の項目は無効化していますので注意してください。
- マルチAZ
- 自動バックアップ
- データベース固有のログ (バイナリ、一般、監査など)
mysqldumpでテーブル定義のインポート
mysqldumpでテーブル定義のみ先に移行しておきます。
まず、移行元のRDSで以下のコマンドを実行し、テーブル定義のデータのみ取得します。
mysqldump -h <移行元RDSのエンドポイント> -u <ユーザー名> -p -B test --no-data --skip-triggers --single-transaction > schema.sql
次に移行先のRDSで以下のコマンドを実行し、先ほど取得したテーブル定義をインポートしておきます。
mysql -h <移行先RDSのエンドポイント> -u <ユーザー名> -p < schema.sql
AWS DMSの設定
DMS側では、レプリケーションインスタンス、エンドポイント、移行タスクを作成する必要があります。
サブネットグループの作成
レプリケーションインスタンスの作成時に必要になるので、サブネットグループを作成します。
今回はプライベートサブネットを2つ選択して構成しました。

レプリケーションインスタンスの作成
レプリケーションインスタンスを作成します。
インスタンスクラスは念の為少し大きめのdms.t3.large
にしています。セキュリティグループは前述で作成したDMS用のもの(DMS-SG)を設定します。
その他は任意の設定で大丈夫です。

ソース、ターゲットエンドポイントの作成
次にエンドポイントを作成します。
まず、ソースエンドポイントには、移行元のRDSへの接続情報を設定します。
項目 | 設定値 |
---|---|
エンドポイントタイプ | ソースエンドポイント |
RDS DBインスタンスの選択 | チェック |
RDSインスタンス | 移行元のRDSインスタンス名を選択 |
エンドポイントデータベースへのアクセス | アクセス情報を手動で提供する |
サーバー名 | RDSインスタンスのエンドポイント |
ポート | 3306 |
ユーザー名 | RDSで設定したユーザー名 |
パスワード | RDSで設定したパスワード |


また、エンドポイント接続のテストで、RDSインスタンスと通信できる状態になっているか確認します。
「レプリケーションインスタンス」には、先ほど作成したレプリケーションインスタンスを選択してテストを実行します。
テストが「successful」になれば疎通できる状態になっています。

ターゲットエンドポイントには、移行先のRDSへの接続情報を設定します。
エンドポイントタイプで「ターゲットエンドポイント」を選択し、ソースエンドポイントの設定と同じように、その他の各設定を埋めていきます。

移行タスクの作成
移行タスクを作成し、移行時の設定を行なっていきます。
各項目をそれぞれ以下のように設定します。
その他は任意の設定で大丈夫です。
項目 | 設定値 |
---|---|
レプリケーションインスタンス | 前述で作成したレプリケーションインスタンス |
ソースデータベースエンドポイント | 前述で作成したソースエンドポイント |
ターゲットデータベースエンドポイント | 前述で作成したターゲットエンドポイント |
移行タイプ | 既存のデータを移行して、継続的な変更をレプリケートする(最初に全てのデータを移行 + その後継続的にデータをレプリケートする設定です) |
ソーストランザクションのカスタム CDC 停止モード | カスタム CDC 停止モードを無効にする |
ターゲットテーブル準備モード | 何もしない |
フルロードの完了後にタスクを停止する | 停止しない |
LOB 列設定 | 完全 LOB モード |
選択ルール > ソース名 | 移行したいデータベース名(今回は「test」データベースを用意しているのでそちらを設定) |
選択ルール > ソーステーブル名 | %(%はワイルドカードなので「test」データベース内の全てのテーブルを指す) |
選択ルール > アクション | 含む |
移行タスクのスタートアップ設定 | 後で手動で行う |





移行タスクの起動
いよいよ移行タスクを起動し、実際に移行を行なってみます。
ちょっとわかりにくいですが、アクションから「再起動/再開」を選択すると、タスクを開始することができます。

このように「ロード完了、レプリケーション進行中」のステータスになっていれば移行タスクが正常に動いています。

移行先のRDSに接続してデータを見てみると、データが移行されてきているのが確認できます。
mysql> SELECT * FROM test.tb_1;
+----+-------------+----------+---------------------+
| ID | name | nickname | registered |
+----+-------------+----------+---------------------+
| 1 | John Doe | JD | 2023-01-01 12:00:00 |
| 2 | Jane Smith | JS | 2023-02-15 08:30:00 |
| 3 | Bob Johnson | BJ | 2023-03-30 18:45:00 |
+----+-------------+----------+---------------------+
3 rows in set (0.002 sec)
また、移行元の方でデータを追加、更新してみます。
INSERT INTO test.tb_1 (name, nickname, registered) VALUES
('Alice Johnson', 'AJ', '2023-04-10 14:20:00');
UPDATE test.tb_1
SET nickname = 'UpdatedNick'
WHERE ID = 1;
実際のデータを確認すると以下のようになります。
mysql> SELECT * FROM test.tb_1;
+----+---------------+-------------+---------------------+
| ID | name | nickname | registered |
+----+---------------+-------------+---------------------+
| 1 | John Doe | UpdatedNick | 2023-01-01 12:00:00 |
| 2 | Jane Smith | JS | 2023-02-15 08:30:00 |
| 3 | Bob Johnson | BJ | 2023-03-30 18:45:00 |
| 4 | Alice Johnson | AJ | 2023-04-10 14:20:00 |
+----+---------------+-------------+---------------------+
4 rows in set (0.002 sec)
そして、移行先の方も見ると自動的にデータの変更が反映されており、継続的にデータが同期されていることが確認できました!(上記と同じ結果なので記載は割愛します)
さいごに
長くなりましたが、AWS DMSを使用して移行を行う際のポイントと、実際の手順をご紹介しました。
DMSの勘所をおさえるのに役立つところがあれば幸いです!