RDS for MySQL から HeatWave on AWS へ DMS レプリケーション

こちらの記事、

- **[東京リージョンにやってきた MySQL HeatWave on AWS を試す (1) 初期設定編](https://qiita.com/hmatsu47/items/8f202eef64ea57e7d948)**

https://qiita.com/hmatsu47/items/8f202eef64ea57e7d948

で、

> > MySQL HeatWave on AWS does not support inbound replication.
>
> インバウンドレプリケーションがサポートされていない点が大きなネックと感じます。

と書きましたが、インバウンドレプリケーションの代わりに DMS の CDC レプリケーションを試してみました。

:::note warn
2023/9/10 時点（MySQL バージョン 8.1.0-u2-cloud）の情報です。
今後、仕様が変わる可能性があります。
:::

:::note
2023/9/10 現在、MySQL HeatWave on AWS の DB 作成画面には PrivateLINK を使うか Public IP Address 経由のアクセスを行うか選択するチェックボックスがあります。

しかし、PrivateLINK を使うのに必要な情報がまだ表示されないので、この記事では Public IP Address 経由のアクセスで試しています。
:::

## 1. ソースとターゲットの DB を作成する

ソース DB として RDS for MySQL 8.0、ターゲット DB として MySQL HeatWave on AWS の DB System を作成します。

:::note
ソース DB で`ROW`形式のバイナリログ（binlog）を有効にするのがポイントです。
今回は RDS for MySQL で試しましたが、Aurora MySQL をソース DB にすることも可能です。
:::

### 1-1. DB パラメータグループを作成する

バイナリログを`ROW`形式で指定する（`binlog_format='ROW'`）RDS for MySQL 8.0 用のパラメータグループを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/9e449c41-c859-e846-bbe0-09ccfe1d12bd.png)

サブネットグループを作成していない場合は、後から作成する DMS のレプリケーションインスタンスからアクセス可能なサブネットグループも作成しておきます。

### 1-2. RDS for MySQL 8.0 インスタンスを作成する

ソース DB を作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/9cfbbbab-ec74-689d-e6ff-4616c2ef0872.png)
- エンジンバージョンは 8.0.34
- インスタンスタイプは任意で
- 後から作成する DMS のレプリケーションインスタンスからアクセス可能なサブネットグループを指定
- 同様に DMS のレプリケーションインスタンスからアクセス可能なセキュリティグループを作成・指定
  - TCP:3306 でインバウンド接続可能に

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/92a8cd1f-a593-bb23-a144-67cdc7ddfd3d.png)
- 先ほど作成した DB パラメータグループを指定
- バックアップ保持期間は 1 日以上を指定
  - バイナリログを有効にするため

### 1-3. ソース DB にテストデータを投入する

テストデータの前にバイナリログ保持期間を設定しておきます。

```sql
mysql> call mysql.rds_set_configuration('binlog retention hours', 168);
```

テストデータはこちらの記事のサンプルデータを、HeatWave ではなく RDS にロード（投入）します。

- **[東京リージョンにやってきた MySQL HeatWave on AWS を試す (2) サンプルクエリ実行編](https://qiita.com/hmatsu47/items/0979f877ad596cf3cf67#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E6%A7%8B%E7%AF%89)**

https://qiita.com/hmatsu47/items/0979f877ad596cf3cf67#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E6%A7%8B%E7%AF%89

:::note
サンプルデータの元の記事はこちらです。
- **[5. サンプルデータベースの構築](https://oracle-japan.github.io/ocitutorials/beginners/creating-HeatWave/#5-%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%81%AE%E6%A7%8B%E7%AF%89)（OCI チュートリアル - その10 - MySQLで高速分析を体験する）**
:::

### 1-4. MySQL HeatWave on AWS の DB System を作成する

こちらの記事を参考に、最小のシェイプで MySQL DB + HeatWave Cluster を作成します。

- **[東京リージョンにやってきた MySQL HeatWave on AWS を試す (1) 初期設定編](https://qiita.com/hmatsu47/items/8f202eef64ea57e7d948)**

https://qiita.com/hmatsu47/items/8f202eef64ea57e7d948

今回は MySQL version を 8.1.0 にしました（2023/9/10 現在、8.0.34 が見当たらなかったため）。

Networking については、「Enable public connectivity」のチェックを入れ、一旦データ確認に使う EC2 の Public IP Address（EC2 が Private Subnet にある場合は NAT インスタンス / NAT Gateway など）だけ登録しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/ad827df4-ba75-e9cd-315d-2ed397a681a2.png)
作成が完了したら、「Hostname」を確認しメモしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/58533138-f580-8d20-ed55-f63840bb7f09.png)

### 1-5. ターゲット DB にデータベース（スキーマ）を作成する

念のため、ターゲット DB（MySQL DB System）にデータベースを作成しておきます。

```sql
CREATE DATABASE tpch;
```

## 2. DMS レプリケーションを設定する

今回はサーバーレスではなく通常のレプリケーションインスタンスを使って設定します。

### 2-1. DMS でレプリケーションサブネットグループを作成する

パブリックサブネットを指定して作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/d06e32f5-f20f-e4b3-0e93-2ea4bcb06c4f.png)

### 2-2. DMS でレプリケーションインスタンスを作成する

テスト用の RDS を小さめのインスタンスで作成したので、レプリケーションインスタンスも小さめで OK です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/6a358811-dce0-919b-ea40-2d4a62886923.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/1ff243eb-163e-0e12-e9f6-9031e9b6c64b.png)

- 先ほど作成したレプリケーションサブネットグループを選択
- 「パブリックアクセス可能」にチェック

### 2-3. EC2 でレプリケーションインスタンスの Public IP Address を確認する

レプリケーションインスタンス作成完了後、EC2 の「ネットワークインターフェイス」で、「dms」で絞り込みをしてレプリケーションインスタンスの「パブリック IPv4 アドレス」を確認しメモしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/e1fbcda2-8f61-4003-8f9e-2ccb85e235fd.png)

### 2-4. MySQL HeatWave on AWS で DB System の Networking 設定を変更する

DMS レプリケーションインスタンスのパブリック IPv4 アドレスを「`;`」（セミコロン）区切りで追記します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/8ba1cea9-b487-f7e2-b2b4-05596d314bfc.png)

### 2-5. DMS でソースエンドポイントを作成する

RDS for MySQL 8.0 のインスタンスを指定して作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/2d46aa44-4a25-1c6d-27f9-05174f4dd475.png)
エンドポイントの接続テストも実施しておきます。

### 2-6. DMS でターゲットエンドポイントを作成する

MySQL HeatWave on AWS の DB System を指定して作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/1ccf3566-0d7c-8330-6e1e-6254d37596ae.png)

先にメモした Hostname を「サーバー名」に指定します。

### 2-7. DMS でデータ移行タスクを作成する

データ移行タスクを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/da8a873f-0168-4a5d-2940-e26bc032ba54.png)

- 先ほど作成したレプリケーションインスタンスとソース・ターゲットのエンドポイントを指定
- 移行タイプは「既存のデータを移行して、継続的な変更をレプリケートする」
  - 初期データの移行と CDC によるレプリケーションの両方を有効化

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/fc9008e4-1384-6dd6-17ea-741bdd0db46d.png)

- 今回のデータでは LOB 列は不要
- 検証とタスクログはお好みで

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/bde6cc80-198c-8afd-29e6-e3b248f6b429.png)

- テーブルマッピングの「選択ルール」でスキーマ名「tpch」の全テーブル（「%」）を「含む」に
- 変換ルールは不使用

:::note
MySQL to MySQL のレプリケーションでは`FLOAT`型・`TIME`型が正しく移行できないので、これらの列が存在する場合は変換ルールで`real4`・`time`に型変換します。
- **[Amazon Aurora MySQL v1（5.6 互換）→ v3（8.0 互換）移行を計画する（8）動作確認](https://zenn.dev/hmatsu47/articles/aurora-mysql3-008-ope-check#4.-%E4%B8%80%E9%80%9A%E3%82%8A%E5%8B%95%E4%BD%9C%E7%A2%BA%E8%AA%8D%E3%82%92%E5%AE%8C%E4%BA%86%E3%81%97%E3%81%9F%E3%82%89%E5%B7%AE%E5%88%86%E3%83%AC%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%EF%BC%88dms-%E3%81%AE-cdc%EF%BC%89%E3%82%92%E3%83%86%E3%82%B9%E3%83%88%E3%81%99%E3%82%8B)**

その他、MySQL to MySQL の DMS レプリケーションにはいくつか気をつけるべき点があります。
- **[小ネタ／AWS DMS（CDC）で MySQL to MySQL 移行時のタイムゾーン指定](https://zenn.dev/hmatsu47/articles/mysql-dms-timezone)**
- **[AWS DMS（CDC）で MySQL to MySQL 移行時の TIMESTAMP 不一致問題](https://zenn.dev/hmatsu47/articles/mysql-dms-cdc-timestamp-mismatch)**
:::

## 3. DMS のレプリケーションを確認する

データ移行タスクを作成したら、初期データの移行（ロード）およびレプリケーションを確認します。

### 3-1. データ移行完了後の状態を確認する

初期データの移行（ロード）完了を待ちます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/642f8929-89f7-0470-fc58-47100246ac60.png)
「テーブル統計」を見てみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/915cca6a-ff31-22b1-63eb-c233f8f9ab3b.png)
ロード完了時点では「挿入」・「削除」・「更新」などの各項目の値は`0`です。

また、ソース DB・ターゲット DB の両方でデータの状態を確認します。

```sql
mysql> USE tpch;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SHOW TABLES;
+----------------+
| Tables_in_tpch |
+----------------+
| customer       |
| lineitem       |
| nation         |
| orders         |
| part           |
| partsupp       |
| region         |
| supplier       |
+----------------+
8 rows in set (0.01 sec)

mysql> SELECT * FROM region;
+-------------+-------------+---------------------------------------------------------------------------------------------------------------------+
| R_REGIONKEY | R_NAME      | R_COMMENT                                                                                                           |
+-------------+-------------+---------------------------------------------------------------------------------------------------------------------+
|           0 | AFRICA      | lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to  |
|           1 | AMERICA     | hs use ironic, even requests. s                                                                                     |
|           2 | ASIA        | ges. thinly even pinto beans ca                                                                                     |
|           3 | EUROPE      | ly final courts cajole furiously final excuse                                                                       |
|           4 | MIDDLE EAST | uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl        |
+-------------+-------------+---------------------------------------------------------------------------------------------------------------------+
5 rows in set (0.00 sec)
```

### 3-2. MySQL HeatWave on AWS で HeatWave へのオフロードを有効にする

こちらの記事のとおり HeatWave へのオフロードを有効にします。

- **[東京リージョンにやってきた MySQL HeatWave on AWS を試す (2) サンプルクエリ実行編](https://qiita.com/hmatsu47/items/0979f877ad596cf3cf67#heatwave-%E3%81%A7%E8%A9%A6%E3%81%99)**

https://qiita.com/hmatsu47/items/0979f877ad596cf3cf67#heatwave-%E3%81%A7%E8%A9%A6%E3%81%99

:::note
元の記事はこちらです。
- **[6. HeatWaveへのデータロード](https://oracle-japan.github.io/ocitutorials/beginners/creating-HeatWave/#6-heatwave%E3%81%B8%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%83%AD%E3%83%BC%E3%83%89)（OCI チュートリアル - その10 - MySQLで高速分析を体験する）**
:::

### 3-3. データを`INSERT`して CDC レプリケーションを確認する

ソース DB（RDS）でデータを 1 行`INSERT`してみます。

```sql
mysql> INSERT INTO region SET R_REGIONKEY = 999, R_NAME = 'SPACE', R_COMMENT = 'outside the earth';
```

先ほどの「テーブル統計」を再確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123899/25282885-8894-7ccf-af8b-a35de412ffb5.png)
対象テーブル（`region`）の「挿入」「適用された挿入」がカウントアップされて`1`になっています。

ターゲット DB（MySQL DB System）で確認してみます。

```sql
mysql> USE tpch;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SELECT * FROM region;
+-------------+-------------+---------------------------------------------------------------------------------------------------------------------+
| R_REGIONKEY | R_NAME      | R_COMMENT                                                                                                           |
+-------------+-------------+---------------------------------------------------------------------------------------------------------------------+
|           0 | AFRICA      | lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to  |
|           1 | AMERICA     | hs use ironic, even requests. s                                                                                     |
|           2 | ASIA        | ges. thinly even pinto beans ca                                                                                     |
|           3 | EUROPE      | ly final courts cajole furiously final excuse                                                                       |
|           4 | MIDDLE EAST | uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl        |
|         999 | SPACE       | outside the earth                                                                                                   |
+-------------+-------------+---------------------------------------------------------------------------------------------------------------------+
6 rows in set (0.00 sec)

mysql> SELECT /*+ SET_VAR(use_secondary_engine=FORCED) */ * FROM region;
+-------------+-------------+---------------------------------------------------------------------------------------------------------------------+
| R_REGIONKEY | R_NAME      | R_COMMENT                                                                                                           |
+-------------+-------------+---------------------------------------------------------------------------------------------------------------------+
|           0 | AFRICA      | lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to  |
|           1 | AMERICA     | hs use ironic, even requests. s                                                                                     |
|           2 | ASIA        | ges. thinly even pinto beans ca                                                                                     |
|           3 | EUROPE      | ly final courts cajole furiously final excuse                                                                       |
|           4 | MIDDLE EAST | uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl        |
|         999 | SPACE       | outside the earth                                                                                                   |
+-------------+-------------+---------------------------------------------------------------------------------------------------------------------+
6 rows in set (0.09 sec)
```

HeatWave も含めてデータが移行＆レプリケーションされているのが確認できました。

```sql
mysql> SELECT
    ->     l_returnflag,
    ->     l_linestatus,
    ->     SUM(l_quantity) AS sum_qty,
    ->     SUM(l_extendedprice) AS sum_base_price,
    ->     SUM(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
    ->     SUM(l_extendedprice * (1 - l_discount) * (1 + l_tax)) AS sum_charge,
    ->     AVG(l_quantity) AS avg_qty,
    ->     AVG(l_extendedprice) AS avg_price,
    ->     AVG(l_discount) AS avg_disc,
    ->     COUNT(*) AS count_order
    -> FROM
    ->     lineitem
    -> WHERE
    ->     l_shipdate <= DATE '1998-12-01' - INTERVAL '90' DAY
    -> GROUP BY l_returnflag , l_linestatus
    -> ORDER BY l_returnflag , l_linestatus;
+--------------+--------------+-------------+-----------------+-------------------+---------------------+-----------+--------------+----------+-------------+
| l_returnflag | l_linestatus | sum_qty     | sum_base_price  | sum_disc_price    | sum_charge          | avg_qty   | avg_price    | avg_disc | count_order |
+--------------+--------------+-------------+-----------------+-------------------+---------------------+-----------+--------------+----------+-------------+
| A            | F            | 37734107.00 |  56586554400.73 |  53758257134.8700 |  55909065222.827692 | 25.522005 | 38273.129734 | 0.049985 |     1478493 |
| N            | F            |   991417.00 |   1487504710.38 |   1413082168.0541 |   1469649223.194375 | 25.516471 | 38284.467760 | 0.050093 |       38854 |
| N            | O            | 74476040.00 | 111701729697.74 | 106118230307.6056 | 110367043872.497010 | 25.502226 | 38249.117988 | 0.049996 |     2920374 |
| R            | F            | 37719753.00 |  56568041380.90 |  53741292684.6040 |  55889619119.831932 | 25.505793 | 38250.854626 | 0.050009 |     1478870 |
+--------------+--------------+-------------+-----------------+-------------------+---------------------+-----------+--------------+----------+-------------+
4 rows in set (1.08 sec)
```