RDS for Oracle のS3 Integration を利用してみた!

# SQL*Plus instant client をインストールして、S3にアップロードしたダンプファイルをRDS for Oracle に落としてみた！
## 概要
2019年2月26日に RDS for Oracle が S3とのデータの受け渡しをすることができるようになりました（https://aws.amazon.com/jp/about-aws/whats-new/2019/02/Amazon-RDS-for-Oracle-Now-Supports-Amazon-S3-Integration/）。
そこで、SQL*Plus をインストールして、S3にアップロードしたファイルをRDS for Oracle にダウンロードするところまで試してみました。
Amazon S3の統合の公式ドキュメントは[こちら](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/oracle-s3-integration.html#oracle-s3-integration.preparing)にあります。

## 流れ
1. SQL*Plus をインストールし、RDS for Oracle に接続します。
2. S3にアップロードしたファイルをDBにダウンロードします。
3. DBのファイルをS3にアップロードします。

## やってみた
### sqlplus のインストール
RDS に接続するために SQL*Plus Instant Client をインストールします。
インストールするパッケージは[こちら](https://www.oracle.com/technetwork/jp/database/database-technologies/instant-client/downloads/index.html) からダウンロードします。 `Basic Package`、 `SQL*Plus Package`です。
また、実行には`VCRUNTIME140.dll` が必要なため、[MicroSoft](https://visualstudio.microsoft.com/ja/downloads/) より"Microsoft Visual C++ 再頒布可能パッケージ"をインストールしておきます。

Oracleからダウンロードしたzip を解凍して一つのディレクトリにまとめます。例として、`C:\Program Files\Oracle\instantclient_19_3` にまとめたファイルを置きます。

環境変数を追加します。

```PowerShell
PS> $systemPath = [System.Environment]::GetEnvironmentVariable("Path", "Machine")
PS> $systemPath += ";C:\Program Files\Oracle\instantclient_19_3"
PS> [System.Environment]::SetEnvironmentVariable("Path", $systemPath, "Machine")

PS> [System.Environment]::SetEnvironmentVariable("NLS_LANG", "JAPANESE_JAPAN.JA16EUC", "Machine")
```


### RDS for Oracle の作成
Oracle DB を RDSに作成します。
今回はテストのため小さめのインスタンスで行います。

設定項目は以下のようにします。
- データベースの設定
  - Standard Create
- エンジンのオプション
  - エンジンのタイプ: Oracle
  - エディション: Oracle Standard Edition Two
  - バージョン: Oracle 18.0.0.0 xxx
  - ライセンス: license-included
- テンプレート
  - 開発/テスト
- 設定
  - インスタンス識別子: database-1
  - マスターユーザ名: デフォルトのまま
  - マスターパスワード: 任意のパスワード
- インスタンスサイズ
  - db.t3.small
- Strage
  - デフォルトのまま
- 追加設定
  - 最初のデータベース名: oracle（デフォルトはORCL）
  - 自動バックアップの有効化を切る

![rds_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250213/b333d5c2-be0e-9df6-fdbc-cb118a344deb.png)

  
作成ボタンを押してしばらくすると利用可能になります。
マスターユーザ名とパスワード、エンドポイントとポートはメモしておいてください。あとで利用します。


### DB に接続してみる
RDSのセキュリティグループを適切に設定すれば、以下のコマンドで接続できるようになるはずです。

```PowerShell
sqlplus admin/${password}@${endpoint}:1521/ORACLE
```

毎回接続情報を入力するのは手間なのでtnsnames.ora を作成します。

```tnsnames.ora
TESTDB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = ${RDSのエンドポイント})(PORT = 1521))
    (CONNECT_DATA =
      (SERVICE_NAME = ORACLE)
    )
  )
```

これを `C:\Program Files\Oracle\instantclient_19_3` に置きます。
環境変数にTNS_ADMIN を追加します。

```PowerShell
PS> [System.Environment]::SetEnvironmentVariable("TNS_ADMIN", "C:\Program Files\Oracle\instantclient_19_3", "Machine")

```

こうすることで、以下のコマンドで接続できるようになりました。

```PowerShell
sqlplus admin/${password}@TESTDB
```

### S3にファイルをアップロードする
S3に適当なバケットを作成します（パブリックアクセスはすべてブロック）。
そこに適当なファイルをアップロードします。
今回は`s3-oracle-integration-test` というバケットを作成して、`test.dmp` をアップロードします。

### DB がS3にアクセスできるようにする
* IAM ポリシーの作成
IAMでs3にアップロードしたオブジェクトを取得できるIAMポリシーを作成します。今回は`s3-oracle-integration-test` という名前のIAMポリシーを作成します。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject", # RDS -> S3 の際に必要
                "s3:GetObject", # S3 -> RDS の際に必要
                "s3:ListBucket" # S3 -> RDS の際に必要
            ],
            "Resource": [
                "arn:aws:s3:::s3-oracle-integration-test/*",
                "arn:aws:s3:::s3-oracle-integration-test"
            ]
        }
    ]
}
```

* IAM ロールの作成
IAMポリシーをIAMロールにアタッチします。
ロールの作成 を選択し、ロールを使用するサービスにRDSを選択します。
アタッチするIAMロールに`s3-oracle-integration-test` を選択し、`s3-oracle-integration-test-role` という名前のIAMロールを作成します。

![rds2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250213/add4eac3-3f44-494b-7a8b-9b14b8e6d728.png)


* IAM ロールをDBインスタンスに関連づける
DBインスタンスの"接続とセキュリティ"タブの下の方に関連付けを行うブロックがあるのでそこで関連づけを行います。

![rds4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250213/0a58a45c-f96e-daec-9f73-7a38531ec226.png)


* S3 Integration を追加したオプショングループを作成する
S3 Integration を利用できるよう、オプショングループを設定します。
新規にオプショングループを作成します。ここでは`s3-oracle-integration-test` というオプショングループを作成します。

![rds5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250213/f5f8e787-a2bf-d0f3-eaa9-7f416a549951.png)

作成したオプショングループに`S3_INTEGRATION` のオプションを追加します。

![rds6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250213/b66c67a9-e425-77bb-193c-74cf13145337.png)


現在のデータベースのオプショングループは`default:oracle-se2-18` なので、これを作成したオプショングループに変更します。

![rds7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250213/b780d6be-f7a5-1bc9-e074-5fb49a03f7b7.png)

### S3 からファイルのダウンロードを行う
DATA_PUMP_DIR の中を確認します。

```
select filename, type, filesize, to_char(mtime,'yyyy/mm/dd hh24:mi:ss') from table(RDSADMIN.RDS_FILE_UTIL.LISTDIR('DATA_PUMP_DIR')) order by mtime;

FILENAME
--------------------------------------------------------------------------------
TYPE         FILESIZE TO_CHAR(MTIME,'YYYY
---------- ---------- -------------------
datapump/
directory        4096 2019/09/27 03:39:15
```

S3にアップロードしたファイルをダウンロードします。

```
SELECT rdsadmin.rdsadmin_s3_tasks.download_from_s3(
  p_bucket_name    =>  's3-oracle-integration-test',
  p_s3_prefix      =>  'test.dmp',
  p_directory_name =>  'DATA_PUMP_DIR')
AS TASK_ID FROM DUAL;

TASK_ID
--------------------------------------------------------------------------------
1569555651590-200
```

返り値であるTASK_IDを利用することでダウンロードのログを確認することができます。

```
SELECT text FROM table(rdsadmin.rds_file_util.read_text_file('BDUMP','dbtask-${TASK_ID}.log'));
```

既に同名のオブジェクトが存在する場合は、上書きされないので、取得したい場合は削除してから行います。

```
begin
  UTL_FILE.FREMOVE ('DATA_PUMP_DIR', 'test.dmp');
end;
/
```

### S3へのファイルのアップロード
`s3-oracle-integration-test` のバケットに `upload` というディレクトリを作成して、DATA_PUMP_DIR のすべてのファイルをアップロードしてみます。

```
SELECT rdsadmin.rdsadmin_s3_tasks.upload_to_s3(
      p_bucket_name    =>  's3-oracle-integration-test', 
      p_prefix         =>  '', 
      p_s3_prefix      =>  'upload/', 
      p_directory_name =>  'DATA_PUMP_DIR') 
   AS TASK_ID FROM DUAL;   
```

## 感想
今までOracle のデータのインポート/エクスポートでは、手元にOracle Database を立ててDB Link を張ってデータを受け渡ししていましたが、これが使えるようになったことで手元にはOracle Instant client をインストールすれば、RDS for Oracle のデータインポートが行えるようになりました。
サイズの大きなダンプファイルをS3に保存できるようになったので、手元に大きめのストレージを用意しなくてもよくなり余計なリソースを確保しなくてもよくなったのがうれしいです。

導入自体も複雑な設定など不要で、現行の運用より楽になると思うので、RDS for Oracle を利用している方はぜひ利用してみるといいと思います。