【MySQL版】AWS DMS の同種データ移行を試してみた (original) (raw)

こんにちは。テクニカルサポート課の森本です。 今回は、AWS DMS の同種データ移行の動作検証を試してみたエントリになります。

AWS DMS の同種データ移行とは

そもそも、AWS DMS が得意とするユースケースは

  1. データベース移行時(切り替え時)のダウンタイムを少なくしたい
  2. 異なるデータベースエンジン間のデータ移行を行いたい

といった場合です。 移行時に十分な停止時間を確保できる場合や、データベースエンジン側のレプリケーションを使用できる場合、DMS を使用することはベストプラクティスではありませんでした。

AWS Black Belt Online Seminar より引用

その背景として、DMS には以下のような制限がありました。

私もお客様から DMS の問い合わせをいただく際、同種のデータ移行の場合は DMS を使わない方がいいですよ、と暗に示していながら回答を行なっていました。

2023年6月にリリースされた DMS の 同種データ移行は、このような DMS のネガティブな側面をカバーしつつ、データベースエンジンのネイティブのレプリケーション方法を使用しながら、ある程度マネージドにシンプルな同種間移行を実現できる機能です。

同種移行の使用

事前準備

こちらのドキュメントの内容に従い進めていきます。

Migrating databases to their Amazon RDS equivalents with AWS DMS - AWS Database Migration Service

環境

今回の環境はソースにRDS MySQL, ターゲットにAurora MySQL を使用します。 ソースに Aurora が指定できないような記載にもみえますが、今回は RDS -> Aurora の移行なので問題なさそうです。

For homogeneous data migrations, you can use on-premises, Amazon EC2, Amazon RDS databases as a source. You can choose Amazon RDS or Amazon Aurora as a migration target for homogeneous data migrations.

Migrating databases to their Amazon RDS equivalents with AWS DMS - AWS Database Migration Service

なお、ここになぜか Document DB(MongoDB) の記載はありませんが、Document DB(MongoDB) の移行にも使用できます。

IAM リソースの作成

以下の内容で 同種移行用の IAM ポリシーを作成し、同種移行用の IAM ロールにアタッチします。 ドキュメントに従い、こちらのポリシーは HomogeneousDataMigrationsPolicy として作成します。

IAMポリシー

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:DescribeRouteTables", "ec2:DescribeSecurityGroups", "ec2:DescribeVpcPeeringConnections", "ec2:DescribeVpcs", "ec2:DescribePrefixLists", "logs:DescribeLogGroups" ], "Resource": "" }, { "Effect": "Allow", "Action": [ "servicequotas:GetServiceQuota" ], "Resource": "arn:aws:servicequotas:::vpc/L-0EA8095F" }, { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:DescribeLogStreams" ], "Resource": "arn:aws:logs:::log-group:dms-data-migration-" }, { "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:::log-group:dms-data-migration-:log-stream:dms-data-migration-" }, { "Effect": "Allow", "Action": "cloudwatch:PutMetricData", "Resource": "" }, { "Effect": "Allow", "Action": [ "ec2:CreateRoute", "ec2:DeleteRoute" ], "Resource": "arn:aws:ec2:::route-table/" }, { "Effect": "Allow", "Action": [ "ec2:CreateTags" ], "Resource": [ "arn:aws:ec2:::security-group/", "arn:aws:ec2:::security-group-rule/", "arn:aws:ec2:::route-table/", "arn:aws:ec2:::vpc-peering-connection/", "arn:aws:ec2:::vpc/" ] }, { "Effect": "Allow", "Action": [ "ec2:AuthorizeSecurityGroupEgress", "ec2:AuthorizeSecurityGroupIngress" ], "Resource": "arn:aws:ec2:::security-group-rule/" }, { "Effect": "Allow", "Action": [ "ec2:AuthorizeSecurityGroupEgress", "ec2:AuthorizeSecurityGroupIngress", "ec2:RevokeSecurityGroupEgress", "ec2:RevokeSecurityGroupIngress" ], "Resource": "arn:aws:ec2:::security-group/" }, { "Effect": "Allow", "Action": [ "ec2:AcceptVpcPeeringConnection", "ec2:ModifyVpcPeeringConnectionOptions" ], "Resource": "arn:aws:ec2:::vpc-peering-connection/" }, { "Effect": "Allow", "Action": "ec2:AcceptVpcPeeringConnection", "Resource": "arn:aws:ec2:::vpc/*" } ] }

また、IAMロールを作成します。IAM ロール名は HomogeneousDataMigrationsRole としました。 アタッチするポリシーは先ほど作成した HomogeneousDataMigrationsPolicy だけでなく、AWS のマネージドポリシーである SecretsManagerReadWrite をアタッチします。これは、後ほど作成する移行プロジェクトにてソース/ターゲットデータベースに接続する際、Secret Manager に保存されているユーザ名/パスワードを使用して接続を行うためです。

信頼ポリシーは通常のサービスとしての dms.amazonaws.com ではなく、以下のように編集が必要でした。

カスタム信頼ポリシー

{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": [ "dms-data-migrations.amazonaws.com", "dms.ap-northeast-1.amazonaws.com" ] }, "Action": "sts:AssumeRole" } ] }

ネットワーク設定

ソース/ターゲットデータベースのロケーションによって、相応の VPC 関連のネットワーク設定を行います。今回はソース/ターゲットともに同じ VPC 内のものを使用するので、特に難しく考える必要はありませんでした。複数の VPC 間やオンプレミスと VPC 間となると、多少複雑なセットアップが必要になりそうです。詳細は以下のドキュメントをご確認ください。

AWS DMSでの同種データ移行用のネットワークのセットアップ - AWS データベース移行サービス

データベース側の設定

ソースデータベースの設定

オンプレミス、MySQL on EC2、RDS for MySQL に限らず必ず必要となる設定について、レプリケーション用のユーザ作成と権限付与があります。 以下のように作成しました。

mysql> CREATE USER 'repluser'@'%' IDENTIFIED BY '***'; Query OK, 0 rows affected (0.06 sec)

mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON . TO 'repluser'@'%'; Query OK, 0 rows affected (0.00 sec)

mysql> GRANT SELECT, RELOAD, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER ON . TO 'repluser'@'%'; Query OK, 0 rows affected (0.01 sec)

mysql> GRANT BACKUP_ADMIN ON . TO 'repluser'@'%'; Query OK, 0 rows affected (0.01 sec)

また、ソース側のbinlog関連のパラメータを以下のように修正しました。すべて動的のパラメータですが、binlog_format を OFF からそれ以外の値(ROWなど)に変更する場合は DB インスタンスを手動で再起動する必要があります。

binlog関連のパラメータ変更内容

バイナリログを有効化したのち、バイナリログの有効期間を設定します。今回は24時間で削除されるよう設定しました。

mysql> call mysql.rds_set_configuration('binlog retention hours', 24); Query OK, 0 rows affected (0.04 sec)

また、テスト用のデータを以下のとおり作成しました。

mysql> create database testdb; Query OK, 1 row affected (0.02 sec)

mysql> use testdb; Database changed mysql> create table t1 (id int primary key, note varchar(256)); Query OK, 0 rows affected (0.04 sec)

mysql> insert into t1 values (1, 'for full load'); Query OK, 1 row affected (0.02 sec)

mysql> insert into t1 values (2, 'for full load'); Query OK, 1 row affected (0.00 sec)

mysql> insert into t1 values (3, 'for full load'); Query OK, 1 row affected (0.00 sec)

mysql> select * from t1; +----+---------------+ | id | note | +----+---------------+ | 1 | for full load | | 2 | for full load | | 3 | for full load | +----+---------------+ 3 rows in set (0.00 sec)

ターゲットデータベースの設定

ターゲット側のデータベースにもレプリケーション用のユーザを作成します。こちらも以下のように作成し、権限付与を行います。 (REPLICATION SLAVE, REPLICATION CLIENTは必要なのかな、という気もしますが一旦はドキュメントのとおり付与します)

mysql> CREATE USER 'repluser'@'%' IDENTIFIED BY '***'; Query OK, 0 rows affected (0.01 sec)

mysql> GRANT ALTER, CREATE, DROP, INDEX, INSERT, UPDATE, DELETE, SELECT, CREATE VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER, EXECUTE, REFERENCES ON . TO 'repluser'@'%'; Query OK, 0 rows affected (0.01 sec)

mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON . TO 'repluser'@'%'; Query OK, 0 rows affected (0.00 sec)

移行プロジェクトの作成

サブネットグループの作成

レプリケーション用のインスタンスプロファイルが使用するサブネットグループを作成します。正直なところ、ドキュメントを見てもどのような要件のサブネットが必要かはっきりしなかったので、一旦ソースやターゲットに指定しているサブネットと同様のサブネットを指定しています。今回はパブリックインターネットを経由しない想定なので、プライベートサブネットを指定しました。

インスタンスプロファイルの作成

インスタンスプロファイルを作成します。レプリケーションインスタンスを作成するようなイメージですが、インスタンスクラス等を選択する必要はありません。また作成時点ではリソースはプロビジョニングされません。

データプロバイダーの作成

データプロバイダーを作成します。ソース/ターゲットエンドポイントを作成するようなイメージですが、インスタンスプロファイルの実体が存在しないため作成時点では接続テストが行われません。

Secret Manager でシークレットを作成

ソース/ターゲット用のデータベース接続情報をシークレットに格納します。 先程作成したレプリケーション用のユーザの情報を入力します。

移行プロジェクトの作成

これまで作成してきたインスタンスプロファイル、データプロバイダー、シークレット、IAMロールを使用して移行プロジェクトを作成します。

データ移行

データ移行の作成

移行プロジェクトの詳細からデータ移行タブに進み、データ移行を作成します。

画面に従いデータ移行を作成します。今回はフルロード + CDC で実行します。CloudWatch Logs は有効化しておくことを強くお勧めします。

データ移行の開始

データ移行を作成しただけでは自動で開始されないので、手動で開始する必要があります。 開始した時点からリソースのプロビジョニングや接続テスト等が行われるため、初回は少し時間がかかります。

After AWS DMS creates your data migration, the status of this data migration is set to Ready. To migrate your data, you must start the data migration manually. To do so, choose your data migration from the list. Next, for Actions, choose Start. For more information, see Managing data migrations.

The first launch of a homogeneous data migration requires some setup. AWS DMS creates a serverless environment for your data migration. This process takes up to 15 minutes. After you stop and restart your data migration, AWS DMS doesn't create the environment again, and you can access your data migration faster.

Creating a data migration in AWS DMS - AWS Database Migration Service

移行結果確認

フルロードの確認

データ移行のステータスが Load complete, replication ongoing になった時点から確認を進めていきます。 ターゲット側で確認します。フルロードが完了しています。

mysql> select * from testdb.t1; +----+-------------------------+ | id | note | +----+-------------------------+ | 1 | for full load | | 2 | for full load | | 3 | for full load | +----+-------------------------+ 3 rows in set (0.01 sec)

CDC の確認

ソース側で以下実行します。

mysql> insert into testdb.t1 values (4,'for CDC'); Query OK, 1 row affected (0.01 sec)

ターゲット側で確認します。 CDC でデータ移行されています。

mysql> select * testdb.from t1; +----+---------------+ | id | note | +----+---------------+ | 1 | for full load | | 2 | for full load | | 3 | for full load | | 4 | for CDC | +----+---------------+ 4 rows in set (0.00 sec)

プロセスの確認

ソース側

レプリケーション用のユーザにて、インスタンスプロファイル(172.16.0.207)からの接続と、ターゲット(10.0.5.225)からの接続があることがわかります。 インスタンスプロファイル側からの接続はフルロード用のダンプ取得のため、ターゲット側からの接続はレプリケーション用のためと考えられます。

mysql> SELECT * FROM information_schema.PROCESSLIST where user = 'repluser'; +----+----------+--------------------+------+-------------+------+---------------------------------------------------------------+------+ | ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO | +----+----------+--------------------+------+-------------+------+---------------------------------------------------------------+------+ | 73 | repluser | 10.0.5.225:28864 | NULL | Binlog Dump | 190 | Master has sent all binlog to slave; waiting for more updates | NULL | | 61 | repluser | 172.16.0.207:50404 | NULL | Sleep | 259 | | NULL | | 63 | repluser | 172.16.0.207:50422 | NULL | Sleep | 258 | | NULL | +----+----------+--------------------+------+-------------+------+---------------------------------------------------------------+------+ 3 rows in set, 1 warning (0.05 sec)

ターゲット側

こちらはインスタンスプロファイル側からの接続のみでした。 ダンプファイルを適用するための接続と考えられます。

mysql> SELECT * FROM information_schema.PROCESSLIST where user = 'repluser'; +-----+----------+--------------------+------+---------+------+-------+------+ | ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO | +-----+----------+--------------------+------+---------+------+-------+------+ | 526 | repluser | 172.16.0.207:45986 | NULL | Sleep | 38 | | NULL | | 527 | repluser | 172.16.0.207:45990 | NULL | Sleep | 12 | | NULL | +-----+----------+--------------------+------+---------+------+-------+------+ 2 rows in set (0.00 sec)

フェイルオーバーの確認

ターゲットの Aurora を手動でフェイルオーバーしてみます。

ソース側

ターゲット側のIPアドレスが変更(10.0.3.118)になっていますが、特に問題なくレプリケーション用のユーザで再接続されています。

mysql> SELECT * FROM information_schema.PROCESSLIST where user = 'repluser'; +----+----------+--------------------+------+-------------+------+---------------------------------------------------------------+------+ | ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO | +----+----------+--------------------+------+-------------+------+---------------------------------------------------------------+------+ | 61 | repluser | 172.16.0.207:50404 | NULL | Sleep | 1382 | | NULL | | 78 | repluser | 10.0.3.118:24610 | NULL | Binlog Dump | 42 | Master has sent all binlog to slave; waiting for more updates | NULL | | 63 | repluser | 172.16.0.207:50422 | NULL | Sleep | 1381 | | NULL | +----+----------+--------------------+------+-------------+------+---------------------------------------------------------------+------+ 3 rows in set, 1 warning (0.01 sec)

ソース側で以下実行します。

mysql> insert into testdb.t1 values (5,'for CDC, after target failover'); Query OK, 1 row affected (0.01 sec)

ターゲット側で確認します。 フェイルオーバー後も特に問題なくレプリケーションできていました。

mysql> select * from testdb.t1; +----+-------------------------+ | id | note | +----+-------------------------+ | 1 | for full load | | 2 | for full load | | 3 | for full load | | 4 | for CDC | | 5 | for CDC, after target failover | +----+-------------------------+ 5 rows in set (0.00 sec)

ただ、フェイルオーバーの間にデータの欠落等が発生している可能性は否めないので、必要に応じてデータ移行の再起動等は実施したほうがいいかもしれません。

以上で無事検証は終了です。

おまけ

データプロバイダーの作成時、エンジンタイプでAurora MySQL を選んでも 後続の設定で RDS データベースインスタンスを選択していると、Aurora クラスターが選択できず、個別の DB インスタンスのみが選択可能です。 ここで誤ってリーダーインスタンスを選択すると、データ移行開始時に以下のエラーが発生してデータ移行できません。(リーダーインスタンスに書き込みしようとしているので当然と言えば当然です)

ERROR 1290: The MySQL server is running with the --read-only option so it cannot execute this statement

手動で入力とし、サーバー名にクラスターエンドポイントを入力しておくことでいつかは幸せになれそうです。

まとめ

今回は DMS の同種移行の検証をやってみました。思ったよりも初期設定が煩雑かつ項目が多く、一つ一つドキュメントと付き合わせながら設定を行う必要がありました。

MySQL では手動のバイナリログレプリケーションを行う場合、ソースでのトランザクションを停止してダンプを取得したり、バイナリログのファイル名とポジションを記録しておいてレプリケーションをスタートするなど諸々の手作業が発生しますが、そのあたりの作業がマネージドに行えるのは嬉しいサービスだと思いました。

RDS -> Aurora の移行であれば RDS 側の機能で Aurora レプリカの作成機能があるので、DMS の同種移行を使用するケースは少ないかもしれませんが、オンプレミスや EC2 インスタンスからの移行であれば試してみる価値はあるのかなと思いました。

この記事がどなたかのお役に立てば幸いです。

森本 晃大(執筆記事の一覧)

テクニカルサポート課

2023年10月入社。絶賛仕事と子育てに奔走中です。