RDS（Oracle）にDMPをインポート（datapump）してみた！

#OracleRDSにDMPをインポート
ちょっとハマってしまったので、以下参考までに。
ポイントは
・S3が必要
・SQLで処理している頭に切り替える。（OSコマンドは使えない。）
・ファイルの大文字小文字が判別必要
・DMPは大きいのでgzipにしたいのですがアップロードしても解凍できないので回答してからファイル転送が必要

#そもそもRDSとは？
![rds_logo.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256178/53f8f3a1-cfbd-cd78-7a52-6460fffcc106.jpeg)
アマゾンが提供しているデータベースサービスです。
今回はOracleデータベースを前提に、そこにDMPデータをインポートするときのコツを記載します！
いろいろサイトがあったんですが、おそらくAWSのサービスを利用される人向けが多く、Oracleの知識はあるけど。。。って人向けが少なかったんで。
正直ちょっとハマりました。（仕事じゃなきゃ、投げ出してたかも。）

#やりたいこと
RDSの準備ができたら、そこにテーブルやデータ、ストアド、VIEWなんかのオブジェクトを一括でインポートしたいです。
旧来のimpコマンドはサポート外なので、サポートされているimpdpつまり、datapumpを使ってインポートを行おうと思います！

#必要なもの
S3バケットが必須です！
S3にDMPファイルをアップロードして、RDSにアップロード（転送みたいなイメージ）し、インポートを行いました。

よく解説サイトにはAWSのEC2にOracleデータベースサーバがあれば、DBリンクでインポートできる等々が記載がありますが、EC2にOracleデータベースサーバがあればRDSいらないですよね。。。

#使ったSQL
RDSはOSコマンド等が使えないので、OracleのSQLを変更した専用のコマンドをSQLで使用します。
SQLPLUSが一番いいみたいですが、ちょっとわかりにくいのでosqleditでも十分操作できます。
（私的にはosqleditのほうがわかり易かったです。）

##ファイルコピー
下記SQLでファイルをコピーする指示を出します。
最所SELECT文なので、意味がわからなかったですが、パッケージを実行してS3にアップロードしたファイルを転送指示を行い、そのタスクIDを結果として返す処理のようです。

```sql
SELECT rdsadmin.rdsadmin_s3_tasks.download_from_s3(
      p_bucket_name    =>  'db-inport',       
      p_directory_name =>  'DATA_PUMP_DIR') 
     AS TASK_ID FROM DUAL;   
```

S3の指定ディレクトリ（バケット）にあるファイルをすべて移送する処理です。

##アップロード指示確認
タスクIDごとの状況を確認するSQLです。
数ギガのファイルだと数分処理に時間がかかり、最終的にfinishedとなった結果がエラーなのかSUCCESS！なのかを確認します。
何度かSELECTとして結果が変わらない事を確認します。

```sql
select text from table(rdsadmin.rds_file_util.read_text_file('BDUMP','dbtask-1234567890-30.log'));
```

結果が下記。

```sql
2019-11-22 07:52:32.297 UTC [INFO ] This task is about to list the Amazon S3 objects for AWS Region ap-northeast-1, bucket name db-inport, and prefix .
2019-11-22 07:52:32.391 UTC [INFO ] The task successfully listed the Amazon S3 objects for AWS Region ap-northeast-1, bucket name db-inport, and prefix .
2019-11-22 07:52:32.407 UTC [INFO ] This task is about to download the Amazon S3 object or objects in /rdsdbdata/datapump from bucket name db-inport and key DMP01.dmp.
2019-11-22 07:53:38.647 UTC [INFO ] The task successfully downloaded the Amazon S3 object or objects from bucket name db-inport with key DMP01.dmp to the location /rdsdbdata/datapump.
2019-11-22 07:53:38.647 UTC [INFO ] The task finished successfully.
```

プリフィックスを間違えていて、空振りしてもSUCCESS！になるので、よく読まないといけません。
これで３時間くらいにらめっこしていて、「大文字小文字！」って気がついたとき泣きそうになりました。。。（みんなには内緒です。）

##ディレクトリの内容確認
ディレクトリのファイル名等を確認します。

```sql
select * from TABLE(RDSADMIN.RDS_FILE_UTIL.LISTDIR('DATA_PUMP_DIR')) ORDER BY MTIME;
```

結果はディレクトリのみであれば、ディレクトリのレコードが１レコードかえってきます。
ファイルがあれば、ファイルレコードがかえってきます。
処理の途中でもかえってくるので、上記のログをしっかりと確認する必要があります。

##DATAPUMPインポート指示
下記のSQLで実行します。
エラーがわかりにくいです。ものすごく。
ファイル名が大文字小文字が違っていると、
「ORA-39001: 引数値が無効です」となり、全くわかりません。
他の解説サイトと少し変えてエラーの詳細をコマンドラインに返すように変更しています。

```sql
DECLARE
hdnl NUMBER;
vMsg  VARCHAR2(2048);
BEGIN
hdnl := DBMS_DATAPUMP.open(operation=>'IMPORT', job_mode=>'SCHEMA', remote_link=>null, job_name=>null, version=>'COMPATIBLE');
DBMS_DATAPUMP.ADD_FILE(handle=>hdnl, filename=>'DMP01.dmp', directory=>'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_dump_file);
DBMS_DATAPUMP.ADD_FILE(handle=>hdnl, filename=>'IMPORT.LOG', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_log_file);
DBMS_DATAPUMP.METADATA_FILTER(hdnl,'SCHEMA_EXPR','IN (''HOGE'')');
DBMS_DATAPUMP.start_job(hdnl);
EXCEPTION
    WHEN OTHERS THEN
        vMsg := SQLERRM(SQLCODE);
        DBMS_OUTPUT.PUT_LINE(vMsg);
END;
```

実行結果は、実行しました！のみなので、下記のSQLやログを確認です。

##途中の内容は下記のSQLでテーブル数を確認します。
```sql
select count(*) from dba_tables where owner='HOGE';
```
※目安ですね。

##ログをS3にダウンロードして、S3からファイルをダウンロードして確認します。
```sql
SELECT rdsadmin.rdsadmin_s3_tasks.upload_to_s3(
        p_bucket_name => 'db-inport',
        p_directory_name => 'DATA_PUMP_DIR',
        p_s3_prefix => 'db-inport/',
        p_prefix => 'IMPORT.LOG')
   AS TASK_ID FROM DUAL;
```

結果は同じく、

```sql
select text from table(rdsadmin.rds_file_util.read_text_file('BDUMP','dbtask-1234567890-30.log'));
```
で確認できます！

S3にディレクトリが作成され、ファイルがダウンロードされていると思うので、WinSCP等でローカルにダウンロードしてファイルを確認や別のサーバに持っていくことができますね。
 
以上です。
そもそものAWSのS3の設定は下記を参考にしました。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/oracle-s3-integration.html

#まとめ
通常のWindowsサーバやLinuxサーバにOracleデータベースをインストールする手間とを考えるとかなり早くサービスインできます。
ただ、細かなパラメータや設定等は自動なのでパフォーマンス障害や接続障害への事前の備えがどこまでできるかはこれから実践して、またフィードバックします！

個人的にですが、定期、随時バックアップや機能改修を考慮したステージング環境を考えると基幹システムのデータベースに利用はちょっと難有りな気がします。
逆に社内テスト環境を爆速で構築したいときにはかなり有用です！ライセンス費用や保守料の心配もいらないので。

総じてお客様への導入を前提にすると、コストとリスクを考えてEC2にデータベースサーバをインストールする方を選択するかも。