Google Cloud DMSでOracleからAlloyDBへ移行しようとしてみた

# はじめに

Google Cloud DMS (Database Migration Service)は、オンプレミス環境や他のパブリッククラウド環境上で稼働しているデータベースをGoogle Cloud上のデータベースへ移行してくれるサービスになります。
例えば、オンプレミス環境のMySQL環境をGoogle Cloud上のCloud SQL for MySQLへの移行であったり、今回トライしたような Oracle DatabaseをPostgreSQLへ変換しつつ移行することが可能です。さらに、初期のスキーマ変換だけではなく、データ移行などもあわせて担う事ができる優れものです。

- [Overview of Database Migration Service](https://cloud.google.com/database-migration/docs/overview)

# やろうとしたこと

今回は移行元データベースとして OCI上のBaseDB(Oracle Database) から、移行先データベースとして Google Cloud 上のAlloyDB for PostgreSQL へ移行しようとしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313926/76fed58c-1994-3cb7-fd23-204e5dd64e36.png)

途中でAlloyDBをDMSのターゲットとする場合には、現時点ではプライベート接続が必要になりかなり設定が大変そうだと思われたため、ターゲットを Cloud SQL for PostgreSQLへ変更しました。

- AlloyDB
    - [Migrate Oracle workloads into AlloyDB for PostgreSQL by using Database Migration Service](https://cloud.google.com/database-migration/docs/oracle-to-alloydb/quickstart)
    - [Configure Private Service Connect for a destination cluster](https://cloud.google.com/database-migration/docs/oracle-to-alloydb/configure-private-service-connect)
- Cloud SQL for PostgreSQL
    - [Migrate Oracle workloads into Cloud SQL for PostgreSQL by using Database Migration Service](https://cloud.google.com/database-migration/docs/oracle-to-postgresql/quickstart)

# DMS設定の流れ

DMSを利用するためには、以下のような流れで実施します。

1. 移行元データベースで事前設定を行う
1. 接続プロファイルの作成
    - 移行元データベース(Oracle Database)への接続プロファイル作成
    - 移行先データベース(Cloud SQL for PostgreSQL)への接続プロファイル
1. コンバージョンワークスペースの作成
    - 移行元データベースからスキーマ情報の取得
    - 取得したスキーマ情報の移行先データベース向けの変換
1. データ移行ジョブを実施

今回は 1. ～ 3. まで、つまり Cloud SQL for PostgreSQL上にスキーマやテーブルを作成するところまで実施しました。

#### 1. 移行元データベースでの事前設定

移行元データベースがOracle Databaseの場合、以下のような設定が事前に必要です。詳細は [「Configure your source Oracle database」](https://cloud.google.com/database-migration/docs/oracle-to-postgresql/configure-your-source-oracle-database)に記載があります。
- アーカイブログモードである事
- サプリメンタルロギングがONになっている事
- 適切な権限を持ったユーザで接続可能である事
    - コンテナデータベースの場合には、ユーザは[CDBの共通ユーザ](https://docs.oracle.com/cd/E57425_01/121/ADMQS/GUID-DA54EBE5-43EF-4B09-B8CC-FAABA335FBB8.htm)である必要がある

<details><summary>サプリメンタルロギングの設定</summary>

```SQL
$ sqlplus sys/xxxxxxxxxxx@oratest.subnetxxxxxxxx.vcnxxxxxxxx.oraclevcn.com:1521/xxxxxxxx.subnetxxxxxxxx.vcnxxxxxxxx.oraclevcn.com as sysdba

SQL*Plus: Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems on Sun Sep 8 10:04:12 2024
Version 23.5.0.24.07

Copyright (c) 1982, 2024, Oracle.  All rights reserved.

Connected to:
Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production
Version 19.24.0.0.0

SQL> ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (all) COLUMNS;

Database altered.

SQL> ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;

Database altered.
```

</details>

<details><summary>移行用の共通ユーザ(c##dms)の設定（CDB$ROOT）</summary>

※手順上は細かい権限で設定ですが、CDB側はdba権限を付与してます
```SQL
$ sqlplus sys/xxxxxxxxxxx@oratest.subnetxxxxxxxx.vcnxxxxxxxx.oraclevcn.com:1521/xxxxxxxx.subnetxxxxxxxx.vcnxxxxxxxx.oraclevcn.com as sysdba

SQL*Plus: Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems on Sun Sep 8 07:34:00 2024
Version 23.5.0.24.07

Copyright (c) 1982, 2024, Oracle.  All rights reserved.


Connected to:
Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production
Version 19.24.0.0.0

SQL> grant dba to c##dms;

Grant succeeded.

SQL> exit
```

</details>
<details><summary>移行用の共通ユーザ(c##dms)の設定（PDB）</summary>

```SQL
$ sqlplus sys/xxxxxxxxxxx@oratest.subnetxxxxxxxx.vcnxxxxxxxx.oraclevcn.com:1521/PDBTEST.subnetxxxxxxxx.vcnxxxxxxxx.oraclevcn.com as sysdba

SQL*Plus: Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems on Sun Sep 8 07:42:15 2024
Version 23.5.0.24.07

Copyright (c) 1982, 2024, Oracle.  All rights reserved.

Connected to:
Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production
Version 19.24.0.0.0

SQL> GRANT CREATE SESSION TO C##DMS;
GRANT SET CONTAINER TO C##DMS;
GRANT SELECT ANY TABLE TO C##DMS;

Grant succeeded.

SQL>
Grant succeeded.

SQL> GRANT SELECT ANY DICTIONARY TO C##DMS;

Grant succeeded.

SQL>
Grant succeeded.

SQL> GRANT SELECT ON SYS.V_$DATABASE TO C##DMS;
GRANT SELECT ON SYS.V_$ARCHIVED_LOG TO C##DMS;
GRANT SELECT ON DBA_SUPPLEMENTAL_LOGGING TO C##DMS;
GRANT SELECT ON DBA_EXTENTS TO C##DMS;
Grant succeeded.

SQL>
Grant succeeded.

SQL>
Grant succeeded.

SQL>

Grant succeeded.

SQL>
```
</details>

#### 2. 接続プロファイルの作成

###### 移行元データベース(Oracle Database)への接続プロファイル作成

移行元データベースとなるOracle Databaseへの接続プロファイルを作成します。

- [Create an Oracle connection profile](https://cloud.google.com/database-migration/docs/oracle-to-postgresql/create-connection-profiles#create-oracle-connection-profile)

接続するデータベースエンジンは「Oracle」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313926/946478d1-7770-9371-ccb8-a599afa85e29.png)

接続方法は、今回は「IP許可リスト」を選択しています。
東京リージョンの場合は次図の5つのIPアドレスを許可する必要があります。

![06-DMS接続定義-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313926/da8aeeeb-857a-c721-9a1e-2402ce01ea37.png)

Oracle Database側のファイヤウォール設定で上記の5つのIPアドレスの接続を許可しています。(TCPの1521のみで良いと考えてます)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313926/691fd698-e666-1b9b-a4d8-b8f53ed1e340.png)

設定に問題がなければ、接続テストが成功してプロファイル作成を行うことが可能です。

![08-DMS接続定義-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313926/02d08fef-7b01-9bbc-d95d-09de6d8ea798.png)

###### 移行先データベース(Cloud SQL for PostgreSQL)への接続プロファイル

同様に移行先データベース向けの接続プロファイルを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313926/1bb2c619-adf9-a047-37f3-83d199070980.png)

今回は「パブリックIP」を選択し、接続テストを行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313926/d2b633ff-2844-baed-332b-49b4e621b226.png)


#### 3. コンバージョンワークスペースの作成

コンバージョンワークスペースとは、データベースマイグレーションに伴うスキーマ変換などを行う空間になります。今回は 移行元データベースであるOracle Databaseの定義を移行先データベースである PostgreSQLの定義に変換を行っています。

- [Work with conversion workspaces](https://cloud.google.com/database-migration/docs/oracle-to-postgresql/work-with-conversion-workspace)

まずは移行元データベースと移行先データベースを設定してコンバージョンワークスペースを作成します。

![71-conversion-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313926/f0ae17a2-3864-a2f4-6f90-c302f59e9ce1.png)


###### 移行元データベースからスキーマ情報の取得

移行元となるOracle Databaseへ接続し、スキーマ定義を取得します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313926/e477cdf9-9128-e10d-c5dd-128352eb8d56.png)

取得したスキーマ定義をCloud SQL for PostgreSQL向けに変換します。

![73-conversion-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313926/588123f8-d6f0-a4ac-686c-cb47b86321e6.png)

変換を行った結果が次図になります。
「PRODUCT_REVIEWS」というVIEWのみ必要なアクションがあるようです。
中身を確認すると、OracleのJSON_TABLEという関数がPostgreSQLにはないので、変換が提案されています。
＃正しい変換なのかの確認はできてません・・

![74-conversion-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313926/9bf96315-b684-3c0f-b9ab-b134d1930d80.png)


###### 取得したスキーマ情報の移行先データベース向けの変換

コンバージョンワークスペースで設定した定義を移行先データベースに適用します。

- [Apply schema to destination](https://cloud.google.com/database-migration/docs/oracle-to-postgresql/work-with-conversion-workspace#apply-to-dest)

コンバージョンワークスペースではViewや制約などについても変換を行いましたが、データ移行前のスキーマの段階ではテーブル本体と主キー制約のみの適用が推奨されていますので、今回はテーブルと主キー制約、そしてシーケンスがテーブル定義に依存しているためシーケンスも移行してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313926/3eaede43-6aff-e8c4-a2d8-cb41eb99889e.png)

![91-tekiyou-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313926/1b38394a-597a-58a9-d89c-14e4d5818ba6.png)

無事適用が完了しました。
Cloud SQL for PostgreSQL上でもオブジェクトが作成されていることが次の通り確認できます。

```SQL
postgres=> select schemaname, tablename, tableowner from pg_tables where schemaname='co';
 co         | order_items | postgres
 co         | customers   | postgres
 co         | inventory   | postgres
 co         | orders      | postgres
 co         | products    | postgres
 co         | shipments   | postgres
 co         | stores      | postgres
```

#### 4. データ移行ジョブを実施

スキーマ変換後、そのままデータ移行ジョブも作成することが可能です。
ただ、今回は 移行元のテーブルに主キー制約がない、というエラーが出てしまい解消できませんでした。
＃主キーは全てのテーブルに設定されています

![101-ikou-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313926/976df90e-e822-b243-eb6e-ef0c0a64534f.png)

```SQL
SQL> select owner, constraint_name, constraint_type, table_name from dba_constraints where owner='CO' and constraint_type='P';

OWNER      CONSTRAINT_NAME                          C TABLE_NAME
---------- ---------------------------------------- - --------------------
CO         CUSTOMERS_PK                             P CUSTOMERS
CO         STORES_PK                                P STORES
CO         PRODUCTS_PK                              P PRODUCTS
CO         ORDERS_PK                                P ORDERS
CO         SHIPMENTS_PK                             P SHIPMENTS
CO         ORDER_ITEMS_PK                           P ORDER_ITEMS
CO         INVENTORY_PK                             P INVENTORY

7 rows selected.
```

# まとめ

データベースの移行については、こういったデータの移行・ジョブなどは実際の移行プロジェクトの中のほんの一部になります。
実際にはアプリケーション側でのノンデグレの確認などが工数の割合としては大半になるでしょう。
しかしながら、スキーマ変換やデータ連携がマネージドで実施することができると作りこみを行う箇所も減らせるので利用しやすくなるでしょう。

現時点では移行元はともかく、移行先のデータベースへの接続方式についてもプライベートの場合には制限が多く、なかなか利用が難しいと思われますが、そちらはGoogle Cloud内で完結しているのでいずれ制約がなくなると期待できます。

いずれにせよ、スキーマ変換などは現状でも利用できるため（そしてスキーマ変換だけなら無料）、移行を検討している場合や移行を検討していなくても将来のためにうちのデータベースはどんな感じなのかな？という事を確認してみても良いかもしれません。