2025/07/09

AWSのSCTとDMSを試す

今回、SCTとDMSを使用して、オンプレミスにあるOracleをAWSのRDSへ移行してみる。
- [AWS Schema Conversion Toolとは](https://docs.aws.amazon.com/ja_jp/SchemaConversionTool/latest/userguide/CHAP_Welcome.html)
- [AWS Database Migration Serviceとは](https://docs.aws.amazon.com/ja_jp/dms/latest/userguide/Welcome.html)


## 典型的な構成イメージ
```
[オンプレ Oracle DB]
        │
   (VPN / Direct Connect)
        │
[AWS VPC内 EC2(SCTインストール)]
        │
        ├── JDBC接続 → オンプレ Oracle
        └── JDBC接続 → RDS for MySQL(ターゲットDB)

[AWS DMS Replication Instance(同じVPC内)]
        ├── 接続 → オンプレ Oracle(VPN経由)
        └── 接続 → RDS for MySQL
```

## 必要な穴あけ
- SCT用EC2のセキュリティグループ
  - アウトバウンド:ソースDB(オンプレ Oracle)とターゲットDB(RDS for MySQL)への JDBC ポート(通常 1521 や 3306)を許可
  - インバウンド:必要に応じて SSH(22)などを制限付きで許可
- DMSレプリケーションインスタンスのセキュリティグループ
  - アウトバウンド:ソースDB(オンプレ Oracle)とターゲットDB(RDS for MySQL)へのTCPポート(1521 や 3306)を許可
  - インバウンド:基本的に不要(DMSはアウトバウンド接続)
- ターゲットDB(RDS for MySQL)のセキュリティグループ
  - インバウンド:SCT用EC2 と DMSインスタンスのセキュリティグループからの接続を許可。ポートは DBエンジンに応じて(例:MySQLなら 3306)
- オンプレ側のファイアウォール設定
  - SCTとDMSからの接続元IP(またはVPN経由のCIDR)を許可
  - Oracleリスナーのポート(1521)を開放

## 今回の構成イメージ
ここではオンプレミスとしてデータセンターの代わりに自宅からAWSへ接続します。
また、SCTは自宅LAN側のPC内に配置します。
```
[自宅 LAN内 Oracle DB]
        │
[自宅 LAN内 PC(SCTインストール)]
        │
        ├── JDBC接続 → 自宅 LAN内 Oracle
        │
   (インターネット)
        │
        └── JDBC接続 → RDS for MySQL(ターゲットDB)

[AWS VPC内 AWS DMS Replication Instance]
        ├── 接続 → 自宅 LAN内 Oracle(インターネット経由)
        └── 接続 → RDS for MySQL
```

## ソースDB(Oracle)を作成
自宅LAN内のPCに仮想マシンを作成し、ソースDBに使用するOracleデータベース環境を構築する。

### Virtualboxで仮想マシン(Windows)を作成
- システム
  - CPU: 1→2
  - メモリ: 2048MB→4096MB
- ストレージを設定
  - OS用: 20GB
  - Oracle用: HDD(15GB)を追加
- ネットワークを設定
  - ブリッジアダプター(ルーターから直接ポート転送するため)

### 仮想マシンのWindowsにOracle XEをインストール
- tnsname.oraを設定
  - ブリッジアダプターのインターフェース(192.168.xx.xx)で起動するように設定
  - 以下を追記 
```
XEPDB1 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.xx.xx)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = XEPDB1)
    )
  )
```
- listener.ora
sqlnet.oraの指定が以下のためlistener.oraは未使用(EZCONNECTは簡易接続ネーミング)
```
NAMES.DIRECTORY_PATH = (TNSNAMES, EZCONNECT)
```

### ユーザ作成、権限付与
**Oracleでは、スキーマ名は基本的にはユーザー名と同じになる。例えば、ユーザー名 testuser を作成した場合、スキーマ名は TESTUSER (大文字) となる。**
```
sqlplus / as sysdba
show con_name
show pdbs
alter session set container=XEPDB1
create user testuser identified by testuser;
grant connect, resource, dba to testuser;
```

### 移行テーブル作成と移行データ投入
```
CREATE TABLE test_datatypes (
    id                  NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    name                VARCHAR2(100),
    description         CLOB,
    price               NUMBER(10,2),
    created_at          DATE,
    updated_at          TIMESTAMP WITH TIME ZONE,
    is_active           CHAR(1),
    category_code       NCHAR(10),
    remarks             NVARCHAR2(200),
    binary_data         BLOB,
    raw_data            RAW(100),
    doc_xml             XMLTYPE,
    unique_id           ROWID,
    float_value         BINARY_FLOAT,
    double_value        BINARY_DOUBLE,
    interval_day_time   INTERVAL DAY TO SECOND,
    interval_year_month INTERVAL YEAR TO MONTH
);
```
```
INSERT INTO test_datatypes (name, description, price, created_at, updated_at, is_active, category_code, remarks, binary_data, raw_data, doc_xml, float_value, double_value, interval_day_time, interval_year_month)
VALUES ('標準データ','一般的な商品の説明',1000.00,TO_DATE('2023-01-01','YYYY-MM-DD'),TO_TIMESTAMP_TZ('2023-01-01 08:00:00 +09:00','YYYY-MM-DD HH24:MI:SS TZH:TZM'),'Y',N'CAT001',N'通常の備考',UTL_RAW.CAST_TO_RAW('sample1'),HEXTORAW('A1B2C3'),XMLTYPE('1'),1.23,12345.6789,INTERVAL '1' DAY + INTERVAL '12:00:00' HOUR TO SECOND,INTERVAL '1-2' YEAR TO MONTH);

INSERT INTO test_datatypes (name, description, price, created_at, updated_at, is_active, category_code, remarks, binary_data, raw_data, doc_xml, float_value, double_value, interval_day_time, interval_year_month)
VALUES ('NULL多め',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);

INSERT INTO test_datatypes (name, description, price, created_at, updated_at, is_active, category_code, remarks, binary_data, raw_data, doc_xml, float_value, double_value, interval_day_time, interval_year_month)
VALUES ('エッジケース',RPAD('x',32000,'x'),0,SYSDATE,SYSTIMESTAMP,'N',N'CAT999',N'NULLと空文字の違い確認',UTL_RAW.CAST_TO_RAW(''),HEXTORAW(''),XMLTYPE(''),0.0,-1.0,INTERVAL '0' DAY,INTERVAL '0-0' YEAR TO MONTH);
```

### LAN上のPCからDB接続確認
- 仮想マシンのWindowsファイアーウォールで任意のIPアドレスからのTCP1521の受信を許可
- 以下URLで接続
  jdbc:oracle:thin:@//192.168.xx.xx:1521/xepdb1

### DMSで変更データキャプチャ(CDC)を利用する場合に必要な設定
- 1. サプリメンタルログの有効化
- 2. アーカイブログモードの有効化

#### 1. サプリメンタルログの有効化
サプリメンタル・ロギング(Supplemental Logging)は、OracleデータベースでCDCを行う際に必要な設定。
どの種類のサプリメンタル・ログを有効にするかは選択可能。
```
# データベースレベルでの補足ログ設定
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
# 主すべての列の補足ログを有効化
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;
# テーブル単位で補足ログの有効化
ALTER TABLE TESTUSER.TEST_DATATYPES ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;
```

#### 2. アーカイブログモードの有効化
アーカイブログが未設定の場合、以下のようなエラーが出る。
```
# アーカイブログが無効な場合
E:  To use CDC, the Oracle database must be configured to archived Redo logs [1022313]
# アーカイブログが取得できない場合(パスエラーや権限不足など)
E:  Cannot retrieve Oracle archived Redo log destination ids [1020401]
```
```
sqlplus / as sysdba

# 確認
ARCHIVE LOG LIST;

# データベースをマウント状態に切り替え(オープン状態では変更不可)
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;

# ARCHIVE LOGモードを有効にする
ALTER DATABASE ARCHIVELOG;

# データベースをオープンに戻す
ALTER DATABASE OPEN;

# ログモードを確認
ARCHIVE LOG LIST;

# ここではアーカイブログの保存先を「E:/oracle_db/archivelogs」とする。
# Oracleサービスの実行ユーザーを確認し、アーカイブログ保存先へ書き込み権限を与えること。

# アーカイブログの保存先を定義
ALTER SYSTEM SET LOG_ARCHIVE_DEST_1='LOCATION=E:/oracle_db/archivelogs' SCOPE=SPFILE;

# 変更後の再起動
SHUTDOWN IMMEDIATE;
STARTUP;
```

## 移行先のターゲットデータベースを作成
AWSにRDS for MySQLをセットアップする。
今回はパブリックサブネットに直置き。
DBはRDS作成時に初期DB(testuser)を作成しておく。

```
# MySQL接続
mysql -h xxx.yyy.zzz.rds.amazonaws.com -u admin -ppassword

# DB確認
SHOW DATABASES;

# ユーザ作成
CREATE USER 'testuser'@'%' IDENTIFIED BY 'testuser';

# ユーザ権限付与
GRANT SELECT, SHOW VIEW, CREATE, ALTER, DROP, INDEX, REFERENCES, CREATE VIEW, TRIGGER, CREATE ROUTINE, ALTER ROUTINE, EXECUTE ON *.* TO 'testuser'@'%';

GRANT ALL PRIVILEGES ON testuser.* TO 'testuser'@'%'; 
## LinuxのMySQLは大文字小文字が区別される。「testuser.*」と「TESTUSER.*」は別物

# 権限を適用
FLUSH PRIVILEGES;

# 権限確認
SHOW GRANTS FOR 'testuser'@'%'; 
```

## スキーマの移行
### SCTを設定
#### SCTのインストール
[AWS Schema Conversion Toolのインストール](https://docs.aws.amazon.com/ja_jp/SchemaConversionTool/latest/userguide/CHAP_Installing.Procedure.html)

#### JDBCドライバーのダウンロード
[AWS Schema Conversion Tool用の JDBC ドライバーのインストール](https://docs.aws.amazon.com/ja_jp/SchemaConversionTool/latest/userguide/CHAP_Installing.JDBCDrivers.html)
> ソースデータベースエンジンとターゲットデータベースエンジンの JDBC ドライバーをダウンロードします。
- [Oracle](https://www.oracle.com/database/technologies/appdev/jdbc-downloads.html)
- [MySQL](https://downloads.mysql.com/archives/c-j/)

#### スキーマの変換
1. Convert schema
1. Apply to database

```
# SCTのログ出力先
C:\Users\<ユーザー名>\AppData\Roaming\AWS Schema Conversion Tool\log\
```

## データの移行
### DMSを設定
#### 必要なロール
- dms-vpc-role
- dms-cloudwatch-logs-role

#### レプリケーションインスタンスを作成
- 事前にサブネットグループを作成しておく

今回インターネット経由でソースデータベースへアクセスするため以下を指定。
- ✔ パブリックアクセス可能
#### ソースエンドポイントを作成
- 接続テスト1
```
Test Endpoint failed: Application-Status: 1020912, Application-Message: Log Miner is not supported in Oracle PDB environment Endpoint initialization failed.
```
> AWS DMS が Oracle の PDB(Pluggable Database)環境では LogMiner を使用できないことを示しています。つまり、現在の構成では LogMinerベースのCDC(変更データキャプチャ)方式が使えないということです。
> AWS DMS では、PDB 環境で Oracle をソースにする場合、LogMiner の代わりに Binary Reader を使用する必要があります。


1. DMS ソースエンドポイントの「追加接続属性」に以下を指定
```
useLogMinerReader=N;useBfile=Y;
```

2. PDBユーザーに必要な権限を付与
Binary Reader を使うには、CDB(コンテナDB)側で以下の権限が必要:(上で「*.*」に対してSELECT付与済み)
```
GRANT SELECT ON V_$LOG TO <ユーザー>;
GRANT SELECT ON V_$LOGFILE TO <ユーザー>;
GRANT SELECT ON V_$ARCHIVED_LOG TO <ユーザー>;
GRANT SELECT ON V_$DATABASE TO <ユーザー>;
GRANT SELECT ON V_$THREAD TO <ユーザー>;
GRANT SELECT ON V_$PARAMETER TO <ユーザー>;
GRANT SELECT ON V_$NLS_PARAMETERS TO <ユーザー>;
GRANT SELECT ON V_$TIMEZONE_NAMES TO <ユーザー>;
```

#### ターゲットエンドポイントを作成
作成済みのRDSインスタンスを選択
#### データベース移行タスクを作成
- 移行タイプ
  - フルロードのみ
  - フルロード+CDC
  - CDCのみ

- ターゲットテーブル準備モード
  - ✔ 何もしない
  - ターゲット上のテーブルを削除
  - 切り捨て

- LOB列設定
  - LOB列をを含めない
  - ✔ 完全LOBモード
  - 制限付きLOBモード

- タスクログ
  - ✔ CloudWatch ログの有効化

- テーブルマッピング
移行対象のテーブルを指定する。(今回はTESTUSERスキーマの全テーブル(%)を指定)
マッピングを指定しない場合、ソース側のスキーマ(TESTUSER)と同名のデータベース(TESTUSER)へロードしようとする。
LinuxのMySQLは大文字小文字が区別されるので、以下のマッピングを指定する。
- スキーマ名: TESTUSERをtestuserへマッピング
- テーブル名: TEST_DATATYPESをtest_datatypesへマッピング
```
{
  "rules": [
    {
      "rule-type": "selection",
      "rule-id": "3",
      "rule-name": "include-all",
      "object-locator": {
        "schema-name": "TESTUSER",
        "table-name": "%"
      },
      "rule-action": "include"
    },
    {
      "rule-type": "transformation",
      "rule-id": "1",
      "rule-name": "map-schema",
      "rule-action": "rename",
      "rule-target": "schema",
      "object-locator": {
        "schema-name": "TESTUSER"
      },
      "value": "testuser"
    },
    {
      "rule-type": "transformation",
      "rule-id": "2",
      "rule-name": "rename-table",
      "rule-action": "rename",
      "rule-target": "table",
      "object-locator": {
        "schema-name": "TESTUSER",
        "table-name": "TEST_DATATYPES"
      },
      "value": "test_datatypes"
    }
  ]
}
```

0 件のコメント:

コメントを投稿

人気の投稿