[AWS] RDS for Oracle へ Data Pump インポートするときの DBMS_DATAPUMP パッケージオプション

マネージドサービスであるRDSでは、Data Pumpの一般的なコマンドであるimpdbを使ったインポートが利用できません。そのため、DBMS_DATAPUMPパッケージを利用したPL/SQLでインポートを実行する必要があります。DBMS_DATAPUMPパッケージでデータインポートする上での、さまざまなオプションを紹介します。
2018.03.28

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、菊池です。

まずは、こちらをご覧ください。

RDS for Oracle環境でData Pumpを利用する

Oracle Databaseのデータをインポート/エクスポートするツール、Data Pumpを使ったRDS間でデータ移行を紹介しています。

マネージドサービスであるRDSでは、Data Pumpの一般的なコマンドであるimpdbを使ったインポートが利用できません。そのため、DBMS_DATAPUMPパッケージを利用しインポートを実行する必要があります。

DBMS_DATAPUMPパッケージを使ってインポートする際に指定可能なオプションを紹介します。

DBMS_DATAPUMP パッケージを使ったインポート

フルインポート

まずは基本的なフルインポートのコマンドです。

DECLARE
hdnl NUMBER;
BEGIN
hdnl := dbms_datapump.open (operation => 'IMPORT', job_mode => 'FULL', version => 'COMPATIBLE');
DBMS_DATAPUMP.ADD_FILE( handle => hdnl, filename => 'import.log', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_log_file);
DBMS_DATAPUMP.ADD_FILE(handle => hdnl, filename => 'dumpfile.dmp', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_dump_file);
DBMS_DATAPUMP.START_JOB(handle => hdnl);
end;
/

前提として、インポートするダンプファイルdumpfile.dmpがディレクトリオブジェクトDATA_PUMP_DIRにあることが必要です。また、インポート実行時のログ出力としてimport.logを指定しています。

スキーマを指定したインポート

次に、スキーマを指定したインポートです。job_modeSCHEMAを指定します。インポート対象のスキーマはMETADATA_FILTERプロシージャで指定します。(この場合はSCHEMA_1、SCHEMA_2が対象になります)

DECLARE
hdnl NUMBER;
BEGIN
hdnl := dbms_datapump.open (operation => 'IMPORT', job_mode => 'SCHEMA', version => 'COMPATIBLE');
DBMS_DATAPUMP.ADD_FILE( handle => hdnl, filename => 'import.log', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_log_file);
DBMS_DATAPUMP.ADD_FILE(handle => hdnl, filename => 'dumpfile.dmp', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_dump_file);
DBMS_DATAPUMP.METADATA_FILTER(hdnl,'SCHEMA_LIST',' ''SCHEMA_1'',''SCHEMA_2'' ');
DBMS_DATAPUMP.START_JOB(handle => hdnl);
end;
/

ジョブの完了を待機

DBMS_DATAPUMPパッケージを実行が正常に終了しても、それはあくまでPL/SQLの実行が正常終了しただけで、インポートジョブは継続している場合があります。インポートジョブの完了を待って応答を返す場合には、WAIT_FOR_JOBプロシージャを使用します。

DECLARE
hdnl NUMBER;
status VARCHAR2(20);
BEGIN
hdnl := dbms_datapump.open (operation => 'IMPORT', job_mode => 'SCHEMA', version => 'COMPATIBLE');
DBMS_DATAPUMP.ADD_FILE( handle => hdnl, filename => 'import.log', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_log_file);
DBMS_DATAPUMP.ADD_FILE(handle => hdnl, filename => 'dumpfile.dmp', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_dump_file);
DBMS_DATAPUMP.METADATA_FILTER(hdnl,'SCHEMA_LIST',' ''SCHEMA_1'',''SCHEMA_2'' ');
DBMS_DATAPUMP.START_JOB(handle => hdnl);
DBMS_DATAPUMP.WAIT_FOR_JOB(hdnl,status);
end;
/

統計情報を除外してインポート

11gのダンプデータを12cにインポートする場合など、互換性の問題で統計情報のインポートでエラーが発生することがあります。統計情報はインポート後に再作成することで問題ない場合には、統計情報を除外してインポートすることで余計なエラーを抑止できます。

以下ではMETADATA_FILTERTABLE_STATISTICSを除外しています。

DECLARE
hdnl NUMBER;
status VARCHAR2(20);
BEGIN
hdnl := dbms_datapump.open (operation => 'IMPORT', job_mode => 'SCHEMA', version => 'COMPATIBLE');
DBMS_DATAPUMP.ADD_FILE( handle => hdnl, filename => 'import.log', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_log_file);
DBMS_DATAPUMP.ADD_FILE(handle => hdnl, filename => 'dumpfile.dmp', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_dump_file);
DBMS_DATAPUMP.METADATA_FILTER(hdnl,'SCHEMA_LIST',' ''SCHEMA_1'',''SCHEMA_2'' ');
DBMS_DATAPUMP.METADATA_FILTER(hdnl, 'EXCLUDE_PATH_EXPR', 'IN (''TABLE_STATISTICS'')');
DBMS_DATAPUMP.START_JOB(handle => hdnl);
DBMS_DATAPUMP.WAIT_FOR_JOB(hdnl,status);
end;
/

テーブルを指定してインポート

続いて、テーブル単位でのインポートです。job_modeはTABLEを指定します。

対象のテープルは、METADATA_FILTERプロシージャを2回使って、スキーマを指定した上でテーブルを指定します。この場合、スキーマに指定できるのは1つのみになります。以下ではSCHEMA_1のテーブルTABLE_1とTABLE_2を指定しています。

DECLARE
hdnl NUMBER;
status VARCHAR2(20);
BEGIN
hdnl := dbms_datapump.open (operation => 'IMPORT', job_mode => 'TABLE', version => 'COMPATIBLE');
DBMS_DATAPUMP.ADD_FILE( handle => hdnl, filename => 'import.log', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_log_file);
DBMS_DATAPUMP.ADD_FILE(handle => hdnl, filename => 'dumpfile.dmp', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_dump_file);
DBMS_DATAPUMP.METADATA_FILTER(hdnl,'SCHEMA_LIST',' ''SCHEMA_1'' ');
DBMS_DATAPUMP.METADATA_FILTER(hdnl,'NAME_LIST',' ''TABLE_1'',''TABLE_2'' ', 'TABLE');
DBMS_DATAPUMP.START_JOB(handle => hdnl);
DBMS_DATAPUMP.WAIT_FOR_JOB(hdnl,status);
end;
/

REMAPの指定

METADATA_REMAPプロシージャを使うことで、移行元と異なるスキーマや表領域を指定してインポートが可能です。

以下では、移行元で表領域TABLESPACE_1にあったオブジェクトをTABLESPACE_2にインポートしています。

DECLARE
hdnl NUMBER;
status VARCHAR2(20);
BEGIN
hdnl := dbms_datapump.open (operation => 'IMPORT', job_mode => 'SCHEMA', version => 'COMPATIBLE');
DBMS_DATAPUMP.ADD_FILE( handle => hdnl, filename => 'import.log', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_log_file);
DBMS_DATAPUMP.ADD_FILE(handle => hdnl, filename => 'dumpfile.dmp', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_dump_file);
DBMS_DATAPUMP.METADATA_FILTER(hdnl,'SCHEMA_LIST',' ''SCHEMA_1'',''SCHEMA_2'' ');
DBMS_DATAPUMP.METADATA_FILTER(hdnl, 'EXCLUDE_PATH_EXPR', 'IN (''TABLE_STATISTICS'')');
DBMS_DATAPUMP.METADATA_REMAP(hdnl, 'REMAP_TABLESPACE', 'TABLESPACE_1', 'TABLESPACE_2');
DBMS_DATAPUMP.START_JOB(handle => hdnl);
DBMS_DATAPUMP.WAIT_FOR_JOB(hdnl,status);
end;
/

上記ではREMAP_TABLESPACEで表領域を指定してますが、REMAP_SCHEMAREMAP_TABLEといったオプションも利用できます。

既存テーブルが存在する場合の動作を指定

インポート時に同名のテーブルがすでに存在した場合、その表に対しどのようなアクションをとるか指定が可能です。

SET_PARAMETERオプションのTABLE_EXISTS_ACTIONで指定します。スキーマモードでのデフォルトはSKIPなので、その表へのロードはスキップされますが、以下のようにTRUNCATEと指定することで表をTRUNCATEした上でロードすることもできます。

DECLARE
hdnl NUMBER;
status VARCHAR2(20);
BEGIN
hdnl := dbms_datapump.open (operation => 'IMPORT', job_mode => 'SCHEMA', version => 'COMPATIBLE');
DBMS_DATAPUMP.ADD_FILE( handle => hdnl, filename => 'import.log', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_log_file);
DBMS_DATAPUMP.ADD_FILE(handle => hdnl, filename => 'dumpfile.dmp', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_dump_file);
DBMS_DATAPUMP.SET_PARAMETER(hdnl,'TABLE_EXISTS_ACTION','TRUNCATE');
DBMS_DATAPUMP.METADATA_FILTER(hdnl,'SCHEMA_LIST',' ''SCHEMA_1'',''SCHEMA_2'' ');
DBMS_DATAPUMP.START_JOB(handle => hdnl);
DBMS_DATAPUMP.WAIT_FOR_JOB(hdnl,status);
end;
/

他にREPLACEAPPENDが指定できます。

まとめ

以上です。

うまくオプションを組み合わせることで、移行戦略に合わせたインポートが可能になります。impdbコマンドでは簡単にオプション指定が可能ですが、RDSではDBMS_DATAPUMPを使う必要があります。各プロシージャを使った実行例を紹介しました。