- はじめに
- RDS 上の DATA_PUMP_DIR の操作
- Data Pump によるエクスポート
- Data Pump によるインポート
- Data Pump ジョブのクリーニング
- S3_INTEGRATION の設定
- S3_INTEGRATION によるファイル転送
はじめに
RDS 上の Oracle で Data Pump によるエクスポート/インポートを行う方法について説明します。
Data Pump では、対象のエクスポートファイルやインポートファイルをディレクトリオブジェクトを介してやり取りする必要があり、サーバOSを直接操作できない RDS ではファイルの連携が面倒でした。
旧来は、エクスポートファイルを他の DB に持っていく場合などは、DBLink を経由する必要がありました。ローカルの端末にファイルを持ってくる場合は、ローカルに DB サーバを立てて DBLink を張るなどの対応が必要でした。
しかし現在は、RDS で S3_INTEGRATION を利用することで、Amazon S3 との統合ができ、S3 を介したファイル連携ができるようになりました。
ここでは、RDS 上での Data Pump によるエクスポート/インポートと S3_INTEGRATION でのファイルのやり取りについて説明します。
RDS 上の DATA_PUMP_DIR の操作
Oracle にて Data Pump を使う際には、ディレクトリオブジェクトとして登録した、OS上のディレクトリを使います。
RDS で Data Pump を使う場合は予め登録されている DATA_PUMP_DIR
を使うことになります。
DATA_PUMP_DIR
は以下のようにして確認することができます。
SELECT * FROM dba_directories WHERE directory_name='DATA_PUMP_DIR';
DATA_PUMP_DIR
内のファイル一覧は以下のようにして確認することができます。
SELECT * FROM TABLE(RDSADMIN.RDS_FILE_UTIL.LISTDIR('DATA_PUMP_DIR')) ORDER BY MTIME;
DATA_PUMP_DIR
内のファイルの内容(例えばログファイルexp.log
)は以下のようにして確認することができます。
SELECT TEXT FROM TABLE(RDSADMIN.RDS_FILE_UTIL.READ_TEXT_FILE('DATA_PUMP_DIR', 'exp.log'));
DATA_PUMP_DIR
内のファイルは以下のように削除することができます。
EXEC UTL_FILE.FREMOVE('DATA_PUMP_DIR', 'exp.log');
すこし話がそれますが、以下のようにディレクトリオブジェクトを作成し、
EXEC RDSADMIN.RDSADMIN_UTIL.CREATE_DIRECTORY(p_directory_name => 'ORCLFILES');
作成したディレクトリに対してファイル出力するといったことも可能です。
declare ltype utl_file.file_type; ldir varchar2(100) := 'ORCLFILES'; lfile varchar2(100) := 'LIST.txt'; s varchar2(10) := '|'; begin ltype := utl_file.fopen(ldir, lfile, 'w'); for i in (select OWNER,STATUS from DUMMY) loop utl_file.putf(ltype, i.OWNER||s||i.STATUS); UTL_FILE.NEW_LINE(ltype); end loop; utl_file.fclose(ltype); end; /
Data Pump によるエクスポート
先ほど見た DATA_PUMP_DIR
を使い、スキーマを指定したエクスポートは以下のようになります。
DECLARE v_hdnl NUMBER; status VARCHAR2(20); BEGIN v_hdnl := DBMS_DATAPUMP.OPEN( operation => 'EXPORT', job_mode => 'SCHEMA', job_name => null); DBMS_DATAPUMP.ADD_FILE( handle => v_hdnl, filename => 'exp.dmp', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_dump_file, reusefile => 1); DBMS_DATAPUMP.ADD_FILE( handle => v_hdnl, filename => 'exp.log', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_log_file, reusefile => 1); DBMS_DATAPUMP.METADATA_FILTER( handle => v_hdnl, name => 'SCHEMA_EXPR', value => 'IN (''SCHEMA_1'')'); DBMS_DATAPUMP.START_JOB(handle => v_hdnl); DBMS_DATAPUMP.WAIT_FOR_JOB(handle => v_hdnl, job_state => status); END; /
ダンプファイル exp.dmp
、ログ・ファイル exp.log
は各自好きな名前にすることができます。
上記では、対象スキーマを SCHEMA_1
としているので、各位の環境に合わせて変更する必要があります。なお、このスキーマ名は大文字で書く必要があります。
スキーマモードのエクスポートでは、スキーマは(IN句で指定しているにも関わらず)1つしか指定できませんので注意してください。
その他は基本的にそのままで大丈夫です。reusefile => 0
とすれば、すでにファイルが存在する場合にエラーになります。
エクスポート・ジョブはバックグラウンドジョブとして動作します。
上記では DBMS_DATAPUMP.WAIT_FOR_JOB
でエクスポートジョブの終了を待機しています。
DBMS_DATAPUMP.WAIT_FOR_JOB
により待機しなかった場合は、以下でジョブの状況を確認することができます。
SELECT * FROM DBA_DATAPUMP_JOBS;
テーブル単位でのエクスポート
テーブル単位でエクスポートする場合は、job_mode
を 'TABLE'
として実行します。
... BEGIN v_hdnl := DBMS_DATAPUMP.OPEN( operation => 'EXPORT', job_mode => 'TABLE', job_name => null); ... DBMS_DATAPUMP.METADATA_FILTER( handle => v_hdnl, name => 'SCHEMA_EXPR', value => 'IN (''SCHEMA_1'')'); DBMS_DATAPUMP.METADATA_FILTER( handle => v_hdnl, name => 'NAME_EXPR', value => 'IN (''TABLE_1'', ''TABLE_2'')'); ...
上記例では、METADATA_FILTER
により TABLE_1
と TABLE_2
を対象としています(SQL式により LIKE 抽出なども可能です)。
なお、Oracle では job_mode
として FULL
としてフルバックアップが可能ですが、RDS for Oracle の場合は利用すべきではありません。RDS では、管理ユーザー SYS や SYSDBA へのアクセスは許可されていないため、データディレクトリが損傷し、データベースの安定性に影響を及ぼす可能性があります。
バージョン指定
エクスポートしたファイルのインポート先が決まっている場合は、version
によりバージョン番号を指定することができます(省略時はデフォルトの COMPATIBLE
)。
v_hdnl := DBMS_DATAPUMP.OPEN( operation => 'EXPORT', job_mode => 'SCHEMA', job_name => null, version => '10.0.0');
エクスポート時にはversion
指定なしで、インポート時に指定することもできます。
Data Pump によるインポート
エクスポートデータからのインポート(スキーマ指定)は以下のようになります。
DECLARE v_hdnl NUMBER; status VARCHAR2(20); BEGIN v_hdnl := DBMS_DATAPUMP.OPEN( operation => 'IMPORT', job_mode => 'SCHEMA', job_name => null); DBMS_DATAPUMP.ADD_FILE( handle => v_hdnl, filename => 'exp.dmp', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_dump_file); DBMS_DATAPUMP.ADD_FILE( handle => v_hdnl, filename => 'imp.log', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_log_file, reusefile => 1); DBMS_DATAPUMP.METADATA_FILTER( handle => v_hdnl, name => 'SCHEMA_EXPR', value => 'IN (''SCHEMA_1'')'); DBMS_DATAPUMP.START_JOB(v_hdnl); DBMS_DATAPUMP.WAIT_FOR_JOB(v_hdnl, status); END; /
エクスポート時と同様に、ログ・ファイル imp.log
は各自好きな名前にすることができます。
対象とするダンプファイル exp.dmp
は、DATA_PUMP_DIR
に配備したダンプファイル名を指定します(S3を介したダンプファルのやり取りは後述します)。
テーブル単位でのインポート
インポート対象のテーブルを絞る場合は、METADATA_FILTER
を使います。
v_hdnl := DBMS_DATAPUMP.OPEN( operation => 'IMPORT', job_mode => 'SCHEMA', job_name => null); ... DBMS_DATAPUMP.METADATA_FILTER( handle => v_hdnl, name => 'SCHEMA_EXPR', value => 'IN (''SCHEMA_1'')'); DBMS_DATAPUMP.METADATA_FILTER( handle => v_hdnl, name => 'NAME_EXPR', value => 'IN (''TABLE_1'', ''TABLE_2'')'); ...
指定方法はエクスポート時と同様です。
統計情報を除いたインポート
統計情報が不要な場合は METADATA_FILTER
として以下を付与します。
... DBMS_DATAPUMP.METADATA_FILTER( handle => hdnl, name => 'EXCLUDE_PATH_EXPR', value => 'IN (''TABLE_STATISTICS'')'); ...
既存テーブルの更新/追加
既存テーブルが存在する場合は、TABLE_EXISTS_ACTION
で動作を変更できます。
... DBMS_DATAPUMP.SET_PARAMETER( handle => hdnl, name => 'TABLE_EXISTS_ACTION', value => 'TRUNCATE'); ...
デフォルトは APPEND
で、表の既存の行に新規の行が追加されます。
TRUNCATE
を指定すると、インポートによって行が挿入される前に、既存の表から行が削除されます。
REPLACE
を指定すると、新しい表が作成される前に、既存の表が削除されます。
スキーマのリマップ
エクスポートしたスキーマとは別のスキーマにインポートするには、スキーマ名のリマップを指定します。
... DBMS_DATAPUMP.METADATA_REMAP( handle => v_hdnl, name => 'REMAP_SCHEMA', old_value => 'SCHEMA_1', value => 'SCHEMA_2'); ...
上記では、エクスポートした SCHEMA_1
を SCHEMA_2
としてインポートする例となります。
Data Pump ジョブのクリーニング
DataPumb ジョブの途中でエラーが発生した場合、ジョブが残る場合があります。
DataPumb は処理中に管理テーブルを作成して処理を行うため、この管理テーブルを削除することでジョブをクリーンアップすることができます。
ジョブの状況は以下で確認できます。
SELECT * FROM DBA_DATAPUMP_JOBS;
ここで表示される OWNER_NAME
のスキーマに、JOB_NAME
の名前のテーブルが作成されているので、以下のように削除します。
DROP TABLE <OWNER_NAME>.<JOB_NAME>;
JOB_NAME
は大抵 SYS_IMPORT_SCHEMA_01 といった名前になるので、実際は以下のような感じになります。
DROP TABLE SCOTT.SYS_IMPORT_SCHEMA_01;
末尾の数字は、実行したジョブに応じてカウントアップされたテーブルとなります。
S3_INTEGRATION の設定
先ほどまでは、Data Pump によるエクスポート/インポートでしたが、S3_INTEGRATION により、ダンプファイルをS3に転送したり、S3から取得したりすることができます。
S3_INTEGRATION を使うには、オプショングループに S3_INTEGRATION
を設定し、RDS のインスタンスに紐付ける必要があります。
デフォルトのオプショングループは変更することができないため、新規オプショングループを作成します。
オプショングループから「グループの作成」で対象のエンジンとバージョンを指定します。
名前は適当なものを設定します。
作成したオプショングループを選択し、「オプションを追加」を選択します。
オプションとして S3_INTEGRATION
を選択して追加します。
作成したオプショングループは、RDSインスタンスの [変更] により、新しく作成したオプショングループを設定します。
オプショングループの変更が完了したら、RDS for Oracleの IAM ロールを設定します。
対象のインスタンスを選択し、[IAM ロールの管理]から S3_INTEGRATION
に適用するロールを追加します。
ロールの選択では、s3:GetObject
、s3:ListBucket
、s3:PutObject
の権限を付与したIAMロールを選択します。ここで設定した IAM ロールにて S3 へのアクセスが行われることになります。
なお、ロールの作成は、CLI では以下のようになります(Windows の場合は \
-> ^
)。
最初にポリシーを作成します。
aws iam create-policy \ --policy-name rds-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:::<your-s3-bucket-arn>", "arn:aws:s3:::<your-s3-bucket-arn/*>" ] } ] }'
<your-s3-bucket-arn>
は S3 に作成したバケット名となります。
ロールを作成します。
aws iam create-role \ --role-name rds-s3-integration-role \ --assume-role-policy-document '{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "rds.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }'
ロールにポリシーを割り当てます。
aws iam attach-role-policy \ --policy-arn <your-policy-arn> \ --role-name rds-s3-integration-role
<your-policy-arn>
はポリシー作成時のAmazon リソースネームです。
S3_INTEGRATION によるファイル転送
S3_INTEGRATION
の設定が終われば、SQL により S3 とのファイルのやり取りが可能となります。
S3 へのアップロード
SELECT rdsadmin.rdsadmin_s3_tasks.upload_to_s3( p_bucket_name => 'myBucket', p_directory_name => 'DATA_PUMP_DIR', p_s3_prefix => '', p_prefix => 'exp.dmp') AS TASK_ID FROM DUAL;
DATA_PUMP_DIR
内の exp.dmp
を、S3 バケット myBucket のルートにアップロードしています。
パラメータは以下の通りです。
パラメータ | 説明 |
---|---|
p_bucket_name |
S3 バケット名 |
p_directory_name |
ファイルのアップロード元のディレクトリオブジェクト名 |
p_s3_prefix |
アップロードするファイル名のプレフィックス。空の場合はバケットのルートにアップロードされる。プレフィックスが folder_1/ の場合、S3バケットの folder_1/ にアップロードされる。folder_1/oradb の場合、folder_1/ フォルダ内にoradb というプレフィックスを付与してアップロードされる |
p_prefix |
アップロードするファイル名が一致する必要があるファイル名のプレフィックス。プレフィックスが空の場合は、ディレクトリ内のファイルがすべてアップロードされる |
S3 からのダウンロード
SELECT rdsadmin.rdsadmin_s3_tasks.download_from_s3( p_bucket_name => 'myBucket', p_directory_name => 'DATA_PUMP_DIR', p_s3_prefix => 'exp.dmp') AS TASK_ID FROM DUAL;
パラメータは以下の通りです。
パラメータ | 説明 |
---|---|
p_bucket_name |
S3 バケット名 |
p_directory_name |
ファイルのダウンロード先のディレクトリオブジェクト名 |
p_s3_prefix |
S3からダウンロードするファイル名のプレフィックス。プレフィックスを空にすると、バケットのルートにあるファイルがすべてダウンロードされる(ディレクトリは対象外)。folder_1/ と指定するとfolder_1/ フォルダ内のファイルが全てダウンロードされる。folder_1/oradb の場合、folder_1/ フォルダ内の oradb というプレフィックスに合致するガイルがダウンロードされる |