今回、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 件のコメント:
コメントを投稿