はじめに
故あって、oracleのdmpから全テーブルのデータをcsvファイルにする必要がありました。
その際の作業内容を備忘録的に書きます。
環境用意
dmpを展開するためにoracleが必要です。今回はたまたま使えるAWSアカウントがあったのでRDSを立てることにしました。
RDS for Oracleの立て方、およびSQLPLUSクライアントの用意の仕方は公式が詳しいです。
なお、EC2からRDSに接続するところについては、私は昔ながらのtnsnames.oraを使いました。
$ORACLE_HOME/admin/network/tnsnames.ora
を作成し、中身はこうです。
ORCL =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = xxxx.ap-northeast-n.rds.amazonaws.com)(PORT = 1521))
(CONNECT_DATA =
(SID = DATABASE)
)
)
.dmpの配置
.dmpファイルは一般的にはimpdpコマンドで投入します。impdpは仕様上、DATA_PUMP_DIR
に格納されているdmpファイルを投入元とすると思います。
で、実際のDATA_PUMP_DIR
はたとえば
D:\app\test\admin\orcl\dpdump\
だったりするわけですが、RDSの場合はどうすればいいのでしょうか。
RDSの場合はS3からDATA_PUMP_DIR
にダウンロードできる以下のようなSELECT文が存在します。
SELECT rdsadmin.rdsadmin_s3_tasks.download_from_s3(
p_bucket_name => 'oracle-dmp',
p_s3_prefix => 'datapump/',
p_directory_name => 'DATA_PUMP_DIR')
AS TASK_ID FROM DUAL;
これでDATA_PUMP_DIR
にdmpファイルがダウンロードされるわけですが、私の場合は初回次のエラーが発生しました。
ORA-00904:"ROSADMIN",. "RDSADMINLSS _ TASKS*. "DOMINLOAD_FROMLS3": invalid identifier
無効な識別子です
ということです。一見よくわからないエラーですが、そのままググるとAWSの情報センターのページが出て来ます。
記事の記載のとおり、「DBインスタンスがS3_INTEGRATIONオプションを含むオプショングループに関連付けられていないこと」が原因です。このオプションを関連付けると、PL/SQLパッケージがインストールされるのでしょう。
また、このあたりの情報は次のような記事もあります。これを上から下までひととおりやれば大丈夫そうです。
さて、DBインスタンスにS3_INTEGRATIONオプションを含むオプショングループを関連付けたあと、再度先ほどのコマンドを実行すると、今度はタスクIDが返ります。
SELECT rdsadmin.rdsadmin_s3_tasks.download_from_s3(
p_bucket_name => 'oracle-dmp',
p_s3_prefix => 'datapump/',
p_directory_name => 'DATA_PUMP_DIR')
AS TASK_ID FROM DUAL;
TASK_ID
----------
1694158807308-15
これでタスクが実行されていることがわかります。
このタスクの結果を見るために、次のSELECT文を発行しましょう。logファイルのTaskIDは書き換えてください。
SELECT text FROM table
(rdsadmin.rds_file_util.read_text_file(
'BDUMP', 'dbtask-1694158807308-15.log'));
タスクが成功していたら、以下のようなTEXTが返ってきます。
<省略>
yyyy-MM-dd hh:mi:ss.000 UTC [INFO] This task is about to download the Amazon S3 object or objects in /rdsdbdata/datapump from bucket name oracle-dmp and key datapump/hogehoge.DMP.
yyyy-MM-dd hh:mi:ss.000 UTC [INFO] The task successfully downloaded the Amazon S3 object or objects from bucket name oracle-dmp with key datapump/hogehoge.DMP to the location /rdsdbdata/datapump.
yyyy-MM-dd hh:mi:ss.000 UTC [INFO] The task finished successfully.
DBインスタンスに適切なS3ポリシーをアタッチできていない場合、次のようなエラーでタスクが異常終了している場合があります。
yyyy-MM-dd hh:mi:ss.000 UTC [ERROR] The DB instance doesn't have credentials to access the specified Amazon S3 bucket. To grant access, add the S3_INTEGRATION role to the DB instance.
yyyy-MM-dd hh:mi:ss.000 UTC [INFO ] The task failed.
私は断片的に対応していたのでこうなってしまったのですが、上述した
Amazon S3 と RDS for Oracle を統合する IAM アクセス許可の設定
をひととおりちゃんとやっていれば発生しないと思います。もし発生した場合は、もう一度手順を見直しましょう。
impdp
それでは、配置したdmpをインポートします。
次のコマンドでインポートできます。
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=>'hogehoge.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 (''hogehoge'')');
DBMS_DATAPUMP.start_job(hdnl);
EXCEPTION
WHEN OTHERS THEN
vMsg := SQLERRM(SQLCODE);
DBMS_OUTPUT.PUT_LINE(vMsg);
END;
/
成功すると、
PL/SQL procedure successfully completed.
と出力されます。
試しに適当なSQLでインポートの検証をしましょう。
SELECT COUNT(*) FROM DBA_TABLES WHERE OWNER='hogehoge';
hogehogeスキーマのテーブル数が返ります。
もちろん、impdpのIMPORT.LOGを参照することも可能です。
SELECT * FROM table
(rdsadmin.rds_file_util.read_text_file(
p_directory => 'DATA_PUMP_DIR',
p_filename => 'IMPORT.LOG'));
見づらければ、S3を経由して手元の好きなエディタで参照しましょう。
SELECT rdsadmin.rdsadmin_s3_tasks.upload_to_s3(
p_bucket_name => 'oracle-dmp',
p_directory_name => 'DATA_PUMP_DIR',
p_s3_prefix => 'oracle-dmp/',
p_prefix => 'IMPORT.LOG')
AS TASK_ID FROM DUAL;
これでRDS for Oracleへdmpを展開できました。
あとはログファイルの出力内容に応じて、統計情報の再取得など必要な処理を実行してください。
次は、ここから全テーブルをCSVファイル出力する方法を実践していきます。