Data Pumpを用いたAutonomous Database間のデータ移行

# はじめに
## 概要

2つのAutonomous Database(ADW/ATP)間でデータを移行する方法について記載します。
- ATP : Autonomous Transaction Processing
- ADW : Autonomous Data Warehouse

Clone機能やDB Linkでの連携といった手段はありますが、他のリージョンにインスタンスを複製したいといった場合や、論理的にデータのバックアップしておきたい場合に有用です。


## 前提条件

最新のOracle Instant Clientがインストールされた、コマンド実行用のComputeインスタンスが構成されていること

## 実施イメージ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148299/bf97fab7-dc9b-9a9b-2d76-abffcdf7e177.png)



# 実施手順

以下ではソースDBとターゲットDBについて、ATPなのか、ADWなのか特に明記していませんが、
基本的にソース、ターゲットがATP/ADW、どちらであっても同じ手順です。


## ■ SourceDBからデータをエクスポートする

インスタンス作成時にデフォルトで構成されているディレクトリ・オブジェクト（DATA_PUMP_DIR）を指定することで、ADW/ATPインスタンスが構成されているExadataのローカルストレージ（DBFS）に出力されます。

以下は表単位でエクスポートする例ですが、スキーマ単位で実行することも可能です。

エクスポートの実行

```
expdp userid=<USER>/<PASSWORD>@<connect_string> \
   tables=<table_name> \
   directory=DATA_PUMP_DIR \
   dumpfile=DATA_PUMP_DIR:expdp.dmp \
   logfile=DATA_PUMP_DIR:expdp.log
```

DBMS_CLOUD.PUT_OBJECTによるオブジェクト・ストレージへの書き出しの際に（後述）、単一ファイルのサイズ制限として5GBが上限なので、対象となるデータサイズが大きい場合は、データを分割する必要があります。また出力するデータを圧縮することも可能であり、リージョンを跨いだデータ転送を高速化することができます。

参考 https://docs.oracle.com/cd/E83857_01/paas/autonomous-data-warehouse-cloud/user/dbmscloud-reference.html#GUID-716F0DE7-C669-477E-8AB8-EA42E41ACB12

エクスポートの実行（データ分割、圧縮あり）

```
expdp userid=<USER>/<PASSWORD>@<connect_string> \
   schemas=<schema_name> \
   directory=data_pump_dir \
   filesize=<5GB以下のサイズを指定> \
   parallel=<number_of_OCPU> \
   dumpfile=data_pump_dir:expdp_%U.dmp \
   compression=all \
   compression_algorithm=high \
   logfile=data_pump_dir:expdp.log
```

##  ■ オブジェクト・ストレージ上にバケットを作成する


コンソール左上のハンバーガーアイコンから「オブジェクト・ストレージ」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148299/8a9b9d5a-ddd6-98b8-ffac-5ea5c3232fd8.png)


「バケットの作成」ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148299/820ce6c4-87ee-8585-3804-6e9273962ec8.png)


「バケット名」を入力し、「バケットの作成」ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148299/8a919a2e-bc8b-13b1-23c8-03a8e4e35817.png)


##  ■ 認証トークンの取得する
コンソールの右上のユーザアイコン→「ユーザ設定」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148299/1adf4e66-2f66-fae7-53f5-da69ecd353f9.png)


画面左側の「リソース」の「認証トークン」をクリック
「トークンの生成」ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148299/16120a45-51e5-6f09-89b2-11f51e79e1da.png)



「説明」を入力し、「トークンの生成」ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148299/024bf479-5289-a804-4db3-83a65d0e5bd5.png)



表示されたトークンをコピーする
※ 一度しか表示されないので、別途メモ帳などに保存しておくように。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148299/34a39a9d-a45f-c064-b6e6-4187829d342b.png)





##  ■ Database Credentialの作成（SourceDBに接続して実施）
SQL*Plus等で以下を実行し、オブジェクトストレージへの接続情報を登録します。
oci_usernameはSourceDB内のスキーマではなく、OCIのユーザ名であることに注意してください。
auth_tokenは先の手順で保存した文字列で置き換えます。

```
SET DEFINE OFF;
BEGIN DBMS_CLOUD.create_credential(
	credential_name => 'DATAPUMP_CREDENTIAL',
	username => '<oci_username>',
	password => '<auth_token>');
END;
/
```




##  ■ dmpファイルのコピー（SourceDBに接続して実施）
SQL*Plus等で以下を実行します。
（SourceDBが配置されているExadataのローカルストレージ（DBFS）から、オブジェクトストレージにダンプファイルを出力されます）


```
BEGIN
DBMS_CLOUD.PUT_OBJECT(
  credential_name=>'DATAPUMP_CREDENTIAL',
  object_uri=>'https://swiftobjectstorage.<region>.oraclecloud.com/v1/<namespace_string>/<bucket_name>/expdp.dmp',
  directory_name=>'DATA_PUMP_DIR',
  file_name=>'expdp.dmp');
END;
/
```
現時点では、DBMS_CLOUD.PUT_OBJECTは"*"のようなワイルドカードをサポートしていないため、複数のダンプファイルをオブジェクトストレージに出力する際に、ファイルごとに実施する必要があります。シェルスクリプトでまとめて実行することも可能です。

object_uriについて、以下は、リージョン：London、バケット名：ADW_Bucketの例です。
namespace_stringは、以下オブジェクトストレージの概要画面のネームスペースで示される文字(nrvxxxx3d7)を利用します。


`https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/nrvxxxx3d7/ADW_Bucket/expdp.dmp`


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148299/f6d9b481-e987-4e21-c225-00e610077590.png)

また、上記はSwift互換URIを利用していますが、Oracle Cloud のNative URIを利用することも勿論可能です。


##  ■ Database Credentialの作成（TargetDBに接続して実施）
SQL*Plus等で以下を実行し、TargetDB内に、オブジェクトストレージへの接続情報を登録します。
oci_usernameはTargetDB内のスキーマではなく、OCIのユーザ名であることに注意してください。
auth_tokenは先の手順で保存した文字列で置き換えます。

```
SET DEFINE OFF;
BEGIN DBMS_CLOUD.create_credential(
	credential_name => 'DATAPUMP_CREDENTIAL',
	username => '<oci_username>',
	password => '<auth_token>');
END;
/
```

##  ■ ADWへのインポート（impdp）
インポートを実行します。

インポートの実行（単一のダンプファイルをインポートする場合）

```
impdp userid=admin/<admin_password>@<connect_string> parallel=<number_of_OCPU> credential=DATAPUMP_CREDENTIAL \
  tables=<table_name> directory=DATA_PUMP_DIR \
  dumpfile=https://swiftobjectstorage.<region>.oraclecloud.com/v1/<namespace_string>/<bucket_name>/<dumpfile_name>
  logfile=DATA_PUMP_DIR:impdp.log
```

インポートの実行（複数のダンプファイルをインポートする場合）

```
impdp userid=admin/<admin_password>@<connect_string> schemas=<schema_name> parallel=<number_of_OCPU> \
  credential=DATAPUMP_CREDENTIAL \
  directory=DATA_PUMP_DIR table_exists_action=truncate \
  exclude=index,cluster,indextype,materialized_view,materialized_view_log,materialized_zonemap,db_link \
  partition_options=merge transform=segment_attributes:n transform=dwcs_cvt_iots:y \
  transform=constraint_use_default_index:y \
  dumpfile=https://swiftobjectstorage.<region>.oraclecloud.com/v1/<namespace_string>/<bucket_name>/expdp_%U.dmp \
  logfile=DATA_PUMP_DIR:impdp.log
```
dumpfileについて、以下は、リージョン：London、テナント名：orasejapan、バケット名：ADW_Bucketの例です。（上記PUT_OBJECTを実施した際のURLと同じです）

`https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/orasejapan/ADW_Bucket/expdp.dmp`


# 注意点



# その他

ここではリージョン1(London)のオブジェクト・ストレージから直接リージョン2のADBにインポートしましたが、一旦リージョン2のオブジェクト・ストレージにデータを複製（クロスリージョン・コピー）してから、インポートすることも可能です。

参考：https://qiita.com/tnagakub/items/19954aaf642e997688d8

データの内容によってOCPU数等の要因によって実行時間は変化するので参考値ですが、処理時間は以下のような感じでした。

・パラレル度を大きく設定すれば、Export/Importを高速に処理できる。
・PUT_OBJECTはOCPUの違いで差はない。
・参考までにOCPU=8で圧縮済み10GBのデータだと40分弱



### 参考コマンド

DATA_PUMP_DIRにあるファイル名、ファイルサイズの確認
`SELECT * FROM DBMS_CLOUD.LIST_FILES('DATA_PUMP_DIR');`

DATA_PUMP_DIRにあるファイルの削除
`exec DBMS_CLOUD.DELETE_FILE('DATA_PUMP_DIR',‘expdp.log');`
`exec DBMS_CLOUD.DELETE_FILE('DATA_PUMP_DIR',‘expdp.dmp');`

DataPumpのジョブの確認
`select job_name from DBA_DATAPUMP_JOBS;`

expdpの進行状況の確認
`expdp userid=admin/<admin_password>@<connect_string> attach=SYS_EXPORT_TABLE_01`

進行状況の更新
`Export>status`

ジョブのキャンセル
`Export>kill_job`

### 参考資料

- [Moving Data from Autonomous Data Warehouse to Other Oracle Databases](https://docs.oracle.com/en/cloud/paas/autonomous-data-warehouse-cloud/user/export-data-other-database.html#)