Alibaba CloudのDTSでデーベースのリアルタイム移行(サービスのダウンタイムなし)を試してみた

# 1. DTSとは
DTSはData Transmission Serviceの略語であり、リレーショナルデータベース、NoSQL、OLAP などのデータベース間でデータ移行やリアルタイムのデータ同期などができるマネージドサービスです。

https://www.alibabacloud.com/ja/product/data-transmission-service

AWSのDMSと同じコンセントのサービスですが、DMSよりはできることが多いです。

DTSには主に以下の機能があります。

https://www.alibabacloud.com/help/en/data-transmission-service/latest/what-is-data-transmission-service

- `Data migration`: データソースにあるスキーマや既存のデータやキャプチャされた変更などをターゲットデータベースへ移行する機能
    - オンプレや他社のクラウド上のデータベースをAlibaba Cloudに移行する時に利用
    - データマイグレーション作業が終わったら、タスクを削除するというやり方なので、一回だけのタスクにピッタリです。
- `Data synchronization`：リアルタイムにdata sourcesを`双方向`同期する機能、以下のシナリオで利用されことが多いです。(一回きりのタスクではなく、常時稼働なタスク)
    - DRサイトの構築(マインのサイトから継続的にデータをDRサイトへリアルタイム同期)
    - multi-site(DR用ではなく、２つのサイトは同時にサービスを提供し、end userからのリクエストは自動的に地理的に近いサイトに振り分けられる)間のデータのリアルタイム同期
    - 業務用データベース(OLTPのデータベース)からデータをdata warehouseへ同期
- `Change tracking`: データソースのdataの変更をキャプチャし、publisher/subscriber streamとしてメッセージを第三者に送る
    - 複数のsubscriberに同時にメッセージを送れるのは特徴です。(AWSのSNSに似ているところがあります。)

オンプレからアリババクラウドのRDSへの移行やAWSのRDSからアリババクラウドのRDSへの移行もだいたい同じな流れです。
今回は`Data migration`を利用し、アリババクラウド上のRDSから別のRDSインスタンスにデータを移行してみたいと思います。

# 2. 事前準備
## 1. ２つのRDSインスタンスを作成
- 最小限スペックの２つのインスタンスを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/5c4849b6-171b-e834-5066-21a7802b0db3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/2aa361fe-9936-b829-89ae-ea68c0202b45.png)

## 2. ２つのRDSインスタンスにそれぞれのデータベースアカウントを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/678a958c-72b9-5cf7-c50f-99efbf5c4877.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/66ad3045-2339-9492-3489-d5912e825d77.png)

- 以下のの二種類のアカウントがあり、今回は`Privilaged Account`(管理者)を作ります。
    - `Privilaged Account`(管理者)
    - `Standard Account`(一般ユーザー)
- databaseのアカウントの作成方法は以下をご参考ください。

https://www.alibabacloud.com/help/en/apsaradb-for-rds/latest/create-an-account-on-an-apsaradb-rds-for-mysql-instance

## 3. ソースのRDSインスタンスにデータベースを作成
- RDSインスタンスに接続し、SQLクエリでデータベースも作れますが、RDSのコンソール画面からも簡単にデータベースが作れるので、今回はRDSのコンソール画面から作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/14aa6ae8-1edb-8dff-f30c-5252270a03c8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/268c62de-ebca-41f1-dbbf-182d053f0a70.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/1ec2bf8d-5820-343d-44b5-602093152757.png)


## 4. ローカルPCからRDSインスタンスにアクセスできる
### public endpointを申請
- ローカルPCからRDSインスタンスにアクセスし、データを登録したいのですが、RDSはVPCに作られいてるので、デフォルトとしてはインターネットから直接アクセスできません。インターネット経由でRDSインスタンスにアクセスするためにはpublic endpointを申請する必要があります。
 
:::note info
そもそもインターネットから直接アクエスできてしまうと、セキュリティリスクがあるため、本番環境はなるぶくpublic endpointを作らないようにしましょう。
:::
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/1b017cac-0dcd-2506-fc6b-7406021c692f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/6e081efc-d1ec-15f5-23f0-a66f099b6cf7.png)
### whitelistの設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/e2c0564f-e734-7008-7252-88fce854990f.png)
- `127.0.0.1`の後ろにカンマ区切りで、自分のpublice IPを追加してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/6a77c61d-6aa8-a377-b3ae-5de17f03f399.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/8821a693-4e1b-0070-1d86-19ab82cb167e.png)
- rdsインスタンスの画面を更新すると、以下のようにpublic endpointが表示されることになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/137c4948-918c-34cb-2f2c-1c1ce76e785f.png)


## 5. ソースのデータベースにデータを登録しておく
- ローカルPCからソースのRDSインスタンスに接続した上で、`myguests`の新テーブルを新規作成
    - host：上記のRDSインスタンスのpublic endpoint
    - user：上記RDSのコンソール画面で作られたデータベースアクセスのアカウント
```
% mysql -h*** -u*** -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 72
Server version: 8.0.25 Source distribution

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| __recycle_bin__    |
| dts_test           |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

# RDSのwebコンソールで作られたdts_testというデータベースに切り替える
mysql> use dts_test;
Database changed

mysql> show tables;
Empty set (0.06 sec)

mysql> CREATE TABLE myguests (
    id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    firstname VARCHAR(30) NOT NULL,
    lastname VARCHAR(30) NOT NULL,
    email VARCHAR(50),
    reg_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
    );

mysql> show tables;
+--------------------+
| Tables_in_dts_test |
+--------------------+
| myguests           |
+--------------------+
```
- ２つのレコードを登録します。
```
mysql> insert into myguests(firstname,lastname,email) values("user1","","user1@example.com");
mysql> insert into myguests(firstname,lastname,email) values("user2","","user2@example.com");
mysql> select * from myguests;
+----+-----------+----------+-------------------+---------------------+
| id | firstname | lastname | email             | reg_date            |
+----+-----------+----------+-------------------+---------------------+
|  1 | user1     |          | user1@example.com | 2022-08-02 20:20:00 |
|  2 | user2     |          | user2@example.com | 2022-08-02 20:20:09 |
+----+-----------+----------+-------------------+---------------------+
```
:::note info
1. 移行対象のテーブルにはレコードを一意に識別できるIDを持つ必要があり、つまりはPRIMARY KEYまたはUNIQUE KEY制約を持つ必要があります。そうでない場合、移行先のデータベースには重複したデータレコードが含まれる可能性があります。
1. DTSを利用するためには、ソースのデータベースでbinlog機能を有効にし、binlogを最低24時間保持する必要があります。RDSではデフォルトの状態でもbinlogはすでに有効になっています。念の為に、binlogが有効になっているかどうかは以下の方法で確認してください。(`on`が表示されている場合は、すでに有効になっているということです。)
```
mysql> SHOW GLOBAL VARIABLES LIKE 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | ON    |
+---------------+-------+
```
:::

# 3. DTSタスク作成
- `dts`で検索し、dtsのwebコンソール画面に遷移
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/b1af16d4-2cbe-0dc3-b0e8-5086f0344a02.png)

- 初めてDTSご利用の時はRAMの権限がないため、以下の画面が表示されます。権限を付与しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/ce2b2ab1-7685-5dba-6e9c-0092fbc58501.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/9f378776-38b7-2677-e0c5-b857a090376a.png)

- DTSは`DMS`に統合されているので、以下の画面が表示されます。(右上のアイコンをクリックして、使いたい言語を選択してください。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/60d3820a-cf86-0426-77de-c4096e6a98a3.png)
- デフォルトの状態ではDTSの`Data Synchronization`タブが表示されているようす。左上の`All Functions`をクリックして、`DTS`の`Data Migration`をクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/89b09256-e20e-8828-e817-8e10445cff77.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/7794355c-9a66-4c7a-2407-de2a2789a35c.png)

- regionは`Japan(Tokyo)`以外である場合は、先にregionを変更してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/ea3f346f-8901-182a-bf6d-8bc1a6dbcd9c.png)

- `Create Task`ボタンをクリックして、タスクを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/5360e238-232d-cf4e-eb73-fce61019d163.png)

- ソースとターゲットのの設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/9100df13-8e35-a07e-e77c-b116ad7ee01f.png)
- `Test Connectivity and Proceed`ボタンをクリックして、次の画面へ遷移(以下の画面が表示されたら、ソースとターゲットの情報自体が正しいであるということです。)

- `schema Migration`、`Full Data Migration`と`Increamental Data Migration`３つ全部選択しましょう。
    - 既存のデータ移行完了後、ソースに新規追加されたレコードも同期したい場合は、`Increamental Data Migration`をチェックする必要がある。
    - 移行したいデータベース`dts_test`を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/879b066b-8a9d-7709-5661-50757c8f07ed.png)
- `Advanced Settings`画面で特に変更なしで、そのまま次のステップに行きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/93dde0f9-9259-c116-cef4-f5eab586940d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/55942bdc-d242-de6a-f7ae-183c88130ef7.png)
- Precheckが行われ、特にエラーがなければ、「Next:Purchase Instance」ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/c669f8c7-d3bc-45ac-38cc-d738ea2af391.png)
- DTSのインスタンス classを選択し、「Buy and Start」ボタンをクリック(今回はテストのため、一番小さい`small`を利用)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/324c1b4f-74d9-e432-5ef6-8e8a3381fd4e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/76551aef-220c-8d77-7197-d63f7332b3ea.png)
- タスク実行している(マイグレーション自体はまだ開始されていない)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/418f3f4f-0df5-5df1-40db-fb47b09d77b4.png)
- 20秒(データ量による)程度時間経過すると、以下のようにスキーマと既存のデータのマイグレーションが完了したことが分かる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/da80d240-fe18-2887-bec9-a4b6f9a169cb.png)


# 4. 動作確認
### データがソースからターゲットのデータベースに同期されていることを確認
```
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| __recycle_bin__    |
| dts_test           |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

mysql> use dts_test;
mysql> select * from myguests;
+----+-----------+----------+-------------------+---------------------+
| id | firstname | lastname | email             | reg_date            |
+----+-----------+----------+-------------------+---------------------+
|  1 | user1     |          | user1@example.com | 2022-08-02 20:20:00 |
|  2 | user2     |          | user2@example.com | 2022-08-02 20:20:09 |
+----+-----------+----------+-------------------+---------------------+
```

### ソースのデータベースに新たにレコードをinsertします。
```
mysql> insert into myguests(firstname,lastname,email) values("user3","","user3@example.com");

mysql> select * from myguests;
+----+-----------+----------+-------------------+---------------------+
| id | firstname | lastname | email             | reg_date            |
+----+-----------+----------+-------------------+---------------------+
|  1 | user1     |          | user1@example.com | 2022-08-02 20:20:00 |
|  2 | user2     |          | user2@example.com | 2022-08-02 20:20:09 |
|  3 | user3     |          | user3@example.com | 2022-08-02 20:36:36 |
+----+-----------+----------+-------------------+---------------------+
```
### ターゲットのデータベースを確認(新しいレコードもターゲットのデータベースに同期されました。)

```
mysql> select * from myguests;
+----+-----------+----------+-------------------+---------------------+
| id | firstname | lastname | email             | reg_date            |
+----+-----------+----------+-------------------+---------------------+
|  1 | user1     |          | user1@example.com | 2022-08-02 20:20:00 |
|  2 | user2     |          | user2@example.com | 2022-08-02 20:20:09 |
|  3 | user3     |          | user3@example.com | 2022-08-02 20:36:36 |
+----+-----------+----------+-------------------+---------------------+
```
- DTSのコンソールでも`Incremental Data Migration`が完了していた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/44318997-287f-482b-dda5-196063a38842.png)

# 5. マイグレーションのタスクを削除
- DTSはタスクの稼働時間に応じて課金されます。移行作業が終わったとしても、タスク自体は自動停止にはならなくて、そのまま放置すると、課金されますので、移行作業が終わったタイミングで、タスクも削除しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/692bf1bf-54a5-460c-11f3-2771078b567b.png)

https://www.alibabacloud.com/help/en/data-transmission-service/latest/billing-methods

# 6. まとめ
- DTSはスキーマや既存のデータだけではなく、既存データ移行後、新たに追加(変更)されるレコードもターゲットに同期できる。
- データ移行タスクの作成時に、データベースやテーブルのスキーマを変更するDDL操作を実行すると、タスクの作成に失敗してしまいますので、DDLを実行しないでください。
- `Increamental Data Migration`をチェックせず、タスク実行中にソースインスタンスにデータを書き込んでしまうとソースインスタンスとターゲットインスタンスの間でデータの一貫性が失われます。リアルタイムでデータの一貫性を確保するために、移行タイプとして`schema Migration`、`Full Data Migration`と`Increamental Data Migration`３つ全部選択することをお勧めします。
- DTSは自動的にRDS for MySQLインスタンスに移行先データベースを作成します。しかし、ソース・データベースの名前が無効な場合、データ移行タスクを作成する前に、ターゲットインスタンスでデータベースを手動で作成する必要があります。
- 互換性を確保するために、ソースと移行先のMySQLデータベースで同じエンジン・バージョンを選択することをお勧めします。