0
2

expdpの.dmpから全テーブルのcsvファイルを出力~RDS for Oarcleへimpdpするまで~

Last updated at Posted at 2023-12-26

はじめに

故あって、oracleのdmpから全テーブルのデータをcsvファイルにする必要がありました。
その際の作業内容を備忘録的に書きます。

環境用意

dmpを展開するためにoracleが必要です。今回はたまたま使えるAWSアカウントがあったのでRDSを立てることにしました。
RDS for Oracleの立て方、およびSQLPLUSクライアントの用意の仕方は公式が詳しいです。

なお、EC2からRDSに接続するところについては、私は昔ながらのtnsnames.oraを使いました。
$ORACLE_HOME/admin/network/tnsnames.oraを作成し、中身はこうです。

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文が存在します。

SQL
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が返ります。

SQLPLUS
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は書き換えてください。

SQL
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をインポートします。
次のコマンドでインポートできます。

SQL
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でインポートの検証をしましょう。

SQL
SELECT COUNT(*) FROM DBA_TABLES WHERE OWNER='hogehoge';

hogehogeスキーマのテーブル数が返ります。
もちろん、impdpのIMPORT.LOGを参照することも可能です。

SQL
SELECT * FROM table
    (rdsadmin.rds_file_util.read_text_file(
        p_directory => 'DATA_PUMP_DIR',
        p_filename  => 'IMPORT.LOG'));

見づらければ、S3を経由して手元の好きなエディタで参照しましょう。

SQL
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ファイル出力する方法を実践していきます。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2