Amazon RDS for OracleでS3と直接ファイルをやり取り可能になりました

大栗です。

今までRDS for Oracleは直接S3と連携できずにダンプファイルの受け渡しが不便でした。今回S3と直接連携できるようになったのでご紹介します。

Amazon RDS for Oracle Now Supports Amazon S3 Integration

Amazon RDS for Oracleのデータインポート/エクスポート

Oracle Databaseはデータのインポート/エクスポートにOracle Data Pumpを使用します。しかしOracle Data PumpはダンプファイルをDirectoryオブジェクトにローカルのファイルとして配置します。RDSの場合はOSにログインできずローカルファイルを触ることができないので工夫が必要です。

今までは手元にOracle Databaseを用意してRDS for OracleとDBLinkで接続して、手元のOracle DatabaseのDirectoryオブジェクトにダンプファイルを出力していました。ダンプファイルは大きなファイルになりがちなのでS3などで保存する事が多いと思います。オンプレミスのOracle Databaseと直接DBLinkで接続するか、別途Oracle Databaseを立てる必要があり手間がかかるものでした。

今回のアップデートによりRDS for OracleがS3とファイルを直接やり取りできるようになりました。

やってみた

以下の手順でOracleのS3連携を試してみます。

  1. オプショングループの作成
  2. DBインスタンスの作成
  3. IAM Roleの作成
  4. ダンプファイルの作成
  5. S3へのアップロード/ダウンロード

以下は東京リージョンで検証しています。

オプショングループの作成

S3連携はオプショングループで有効化をします。

RDSコンソールのオプショングループの画面でグループの作成をクリックします。

ここではエンジンバージョンをoracle-se2、メジャーエンジンのバージョンを12.2で作成します。

作成したオプショングループを選択してオプションの追加をクリックします。

オプションはS3_INTEGRATION、バージョンは1.0、すぐに適用ではいを選択して、オプションの追加をクリックします。

DBインスタンスの作成

RDS for OracleのDBインスタンスを起動します。

RDSコンソールのダッシュボードでデータベースの作成をクリックします。

エンジンのオプションでOracleを選択して、エディションでOracle Standard Edition Twoを選択して次へをクリックします。

ここでは開発/テストを選択して次へをクリックします。

ライセンスモデルはライセンス込み、DBエンジンのバージョンはOracle 12.2.0.1.ru-2019-01.rur-2019-01.r1としました。

DBインスタンス識別子やマスターユーザの名前、パスワードを入力して次へをクリックします。

データベースの設定のオプショングループで最初に作成したものを選択します。その他の設定を行いデータベースの作成をクリックします。

DBインスタンスが起動するまで待ちます。

IAM Roleの作成

RDSがS3にアクセスするためのIAM Roleを作成します。

初めに、以下のコマンドでIAMポリシーを作成します。使用する権限はs3:GetObjects3:ListBuckets3:PutObjectの3種類です。<Bucket Name>はアクセス対象のS3のバケット名で置き換えて下さい。

$ aws iam create-policy \
>    --policy-name s3-integration-policy \
>    --policy-document '{
>   "Version": "2012-10-17",
>   "Statement": [
>     {
>       "Sid": "s3integration",
>       "Action": [
>         "s3:GetObject",
>         "s3:ListBucket",
>         "s3:PutObject"
>       ],
>       "Effect": "Allow",
>       "Resource": [
>         "arn:aws:s3:::<Bucket Name>",
>         "arn:aws:s3:::<Bucket Name>/*"
>       ]
>     }
>   ]
> }'
{
    "Policy": {
        "PolicyName": "s3-integration-policy",
        "PermissionsBoundaryUsageCount": 0,
        "CreateDate": "2019-02-28T07:56:41Z",
        "AttachmentCount": 0,
        "IsAttachable": true,
        "PolicyId": "A1B2C3D4E5F6G7H8I9K0L",
        "DefaultVersionId": "v1",
        "Path": "/",
        "Arn": "arn:aws:iam::123456789012:policy/s3-integration-policy",
        "UpdateDate": "2019-02-28T07:56:41Z"
    }
}

RDSにアタッチできるIAM Roleを作成します。

$ aws iam create-role \
>    --role-name s3-integration-role \
>    --assume-role-policy-document '{
>   "Version": "2012-10-17",
>   "Statement": [
>     {
>       "Effect": "Allow",
>       "Principal": {
>          "Service": "rds.amazonaws.com"
>        },
>       "Action": "sts:AssumeRole"
>     }
>   ]
> }'
{
    "Role": {
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Action": "sts:AssumeRole",
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "rds.amazonaws.com"
                    }
                }
            ]
        },
        "RoleId": "A1B2C3D4E5F6G7H8I9K0L",
        "CreateDate": "2019-02-28T07:57:31Z",
        "RoleName": "s3-integration-role",
        "Path": "/",
        "Arn": "arn:aws:iam::123456789012:role/s3-integration-role"
    }
}

Roleにポリシーをアタッチします。

$ aws iam attach-role-policy \
>    --policy-arn arn:aws:iam::123456789012:policy/s3-integration-policy \
>    --role-name s3-integration-role

起動したRDSにIAM Roleを付与します。

$ aws rds add-role-to-db-instance \
>    --db-instance-identifier ora1 \
>    --feature-name S3_INTEGRATION \
>    --role-arn arn:aws:iam::123456789012:role/s3-integration-role

これでRDS for OracleにS3へのアクセス権限が付きました。

ダンプファイルの作成

S3へアップロードするダンプファイルを作成します。

クライアントはAmazon Linux 2を想定しています。

以下のOracleのサイトからInstant Clientをダウンロートします。

Instant Client Downloads for Linux x86-64 (64-bit)

SQL*PLUSを使用するため、以下のファイルをダウンロードしてAmazon Linux 2にインストールします。

  • oracle-instantclient18.3-basic-18.3.0.0.0-3.x86_64.rpm
  • oracle-instantclient18.3-sqlplus-18.3.0.0.0-3.x86_64.rpm

今回は一時的に接続するだけなので、tnsnames.oraの設定を行わずに接続します。

$ export LD_LIBRARY_PATH=/usr/lib/oracle/18.3/client64/lib
1-6-127 ~]$ sqlplus64 awsuser/mypassword@"(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=ora1.a1b2c3d4e5f6.ap-northeast-1.rds.amazonaws.com)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL)))"

SQL*Plus: Release 18.0.0.0.0 - Production on Thu Feb 28 07:43:14 2019
Version 18.3.0.0.0

Copyright (c) 1982, 2018, Oracle.  All rights reserved.

Last Successful login time: Thu Feb 28 2019 07:20:09 +00:00

Connected to:
Oracle Database 12c Standard Edition Release 12.2.0.1.0 - 64bit Production

SQL>

ディレクトリの状態を確認してみます。

SQL> select directory_name, directory_path FROM dba_directories
  2  where directory_name='DATA_PUMP_DIR';

DIRECTORY_NAME
--------------------------------------------------------------------------------
DIRECTORY_PATH
--------------------------------------------------------------------------------
DATA_PUMP_DIR
/rdsdbdata/datapump

サンプル用のテーブルを作成してみます。

SQL> create table sample_table (
  2  col1 int,
  3  col2 varchar(20),
  4  col3 date);

Table created.

SQL> insert into sample_table (col1, col2, col3)
  2    values (1, 'Developers.IO', sysdate);

1 row created.

SQL> commit;

Commit complete.

ダンプファイルを作成します。DBMS_DATAPUMPパッケージを使用して作成します。

SQL> DECLARE
  2  hdnl NUMBER;
  3  BEGIN
  4  hdnl := DBMS_DATAPUMP.open( operation => 'EXPORT', job_mode => 'SCHEMA', job_name=>null);
  5  DBMS_DATAPUMP.ADD_FILE( handle => hdnl, filename => 'tab1.dmp', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_dump_file);
  6  DBMS_DATAPUMP.ADD_FILE( handle => hdnl, filename => 'exp.log', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_log_file);
  7  DBMS_DATAPUMP.METADATA_FILTER(hdnl,'SCHEMA_EXPR','IN (''AWSUSER'')');
  8  DBMS_DATAPUMP.start_job(hdnl);
  9  END;
 10  /

PL/SQL procedure successfully completed.

ディレクトリの中を確認すると、以下のようにファイルが出力されています。

SQL> select * from table
  2  (rdsadmin.rds_file_util.listdir(p_directory => 'DATA_PUMP_DIR'));

FILENAME
------------------------------------------------------------------------------------------------------------------------
TYPE       FILESIZE MTIME
---------- ---------- ---------
datapump/
directory  4096 28-FEB-19

exp.log
file      604 28-FEB-19

tab1.dmp
file    49152 28-FEB-19

S3へのアップロード/ダウンロード

S3へのファイル出力はrdsadmin.rdsadmin_s3_tasks.upload_to_s3を使用します。詳しくは以下のドキュメントをご確認ください。

Transferring Files Between Amazon RDS for Oracle and an Amazon S3 Bucket

以下のコマンドを実行します。するとTASK_IDが返ってきます。

SQL> SELECT rdsadmin.rdsadmin_s3_tasks.upload_to_s3(
  2        p_bucket_name    =>  'bucket-name',
  3        p_prefix         =>  'exp.log',
  4        p_s3_prefix      =>  'dbfiles/',
  5        p_directory_name =>  'DATA_PUMP_DIR')
  6     AS TASK_ID FROM DUAL;

TASK_ID
------------------------------------------------------------------------------------------------------------------------
1234567890123-12

dbtask-<TASK_ID>.logの形式でログが出力されるので内容を確認します。アップロードが成功していました。

SQL> SELECT text FROM table(rdsadmin.rds_file_util.read_text_file('BDUMP','dbtask-1234567890123-12.log'));


TEXT
------------------------------------------------------------------------------------------------------------------------
2019-02-28 08:35:31.686 UTC [INFO ] File #1: Uploading the file /rdsdbdata/datapump/exp.log to Amazon S3 with bucket nam
e bucket-name and key exp.log.

2019-02-28 08:35:31.872 UTC [INFO ] The file /rdsdbdata/datapump/exp.log was uploaded to Amazon S3 with bucket name buck
et-name and key exp.log.

2019-02-28 08:35:31.873 UTC [INFO ] The task finished successfully.

S3も確認してみます。S3側もファイルが有ることが確認できました。

次にS3からファイルをダウンロードしてみます。

S3にtest.txtというファイルを用意します。

rdsadmin.rdsadmin_s3_tasks.download_from_s3でダウンロードします。

SQL> SELECT rdsadmin.rdsadmin_s3_tasks.download_from_s3(
  2        p_bucket_name    =>  'bucket-name
  5     AS TASK_ID FROM DUAL;

TASK_ID
--------------------------------------------------------------------------------
1234567890123-45

ログを確認すると成功しています。

SQL> SELECT text FROM table(rdsadmin.rds_file_util.read_text_file('BDUMP','dbtask-1234567890123-45.log'));

TEXT
--------------------------------------------------------------------------------
2019-03-01 00:08:32.411 UTC [INFO ] This task is about to list the Amazon S3 obj
ects for AWS Region ap-northeast-1, bucket name bucket-name, and prefix dbfiles/
test.txt.

2019-03-01 00:08:32.488 UTC [INFO ] The task successfully listed the Amazon S3 o
bjects for AWS Region ap-northeast-1, bucket name bucket-name, and prefix dbfile
s/test.txt.

2019-03-01 00:08:32.498 UTC [INFO ] This task is about to download the Amazon S3
 object or objects in /rdsdbdata/datapump to bucket name bucket-name and key dbf
 iles/test.txt.

TEXT
--------------------------------------------------------------------------------

2019-03-01 00:08:32.576 UTC [INFO ] The task successfully downloaded the Amazon
S3 object or objects from bucket name bucket-name with key dbfiles/test.txt to t
he location /rdsdbdata/datapump.

2019-03-01 00:08:32.604 UTC [INFO ] The task finished successfully.

ディレクトリの中身にもtest.txtがあり、ちゃんとS3からダウンロードできたことを確認できます。

SQL> select * from table
  2  (rdsadmin.rds_file_util.listdir(p_directory => 'DATA_PUMP_DIR'));

FILENAME
--------------------------------------------------------------------------------
TYPE	     FILESIZE MTIME
---------- ---------- ---------
datapump/
directory	 4096 01-MAR-19

exp.log
file		 1197 28-FEB-19

tab1.dmp
file	       348160 28-FEB-19


FILENAME
--------------------------------------------------------------------------------
TYPE	     FILESIZE MTIME
---------- ---------- ---------
test.txt
file		    9 01-MAR-19

さいごに

いかがでしたか?今までダンプファイルをRDS for Oracleとやり取りするには別途Oracle Databaseサーバーが必要となり大変面倒な作業でした。今回のアップデートによりS3と簡単にファイルをアップロード/ダウンロードできるようになったためデータの受け渡しが簡単になりました。RDS for Oracleを利用されている方には必須となる知識だと思いますので、ご活用ください。