Oracle Data Pump(expdp / impdp)は、Oracle 10g 以降に搭載された高速なデータエクスポート・インポートツールです。旧来の exp / imp コマンドに比べて大幅に高速化されており、スキーマ移行・テーブルデータのバックアップ・本番データの開発環境への移動など、DBA 業務で最も頻繁に使われるツールの一つです。
Data Pump はサーバーサイドで動作します。ダンプファイルは クライアントではなく Oracle サーバー上の DIRECTORY オブジェクトが指すディレクトリに出力されます。この点が旧来の exp/imp と大きく異なるため、まず DIRECTORY の設定から理解する必要があります。
- DIRECTORY オブジェクトの作成と権限付与
- expdp でスキーマ / テーブル / フルデータベースをエクスポートする方法
- QUERY・EXCLUDE・INCLUDE によるエクスポート対象の絞り込み
- impdp の REMAP_SCHEMA・REMAP_TABLESPACE でスキーマ名・表領域名を変えてインポートする方法
- TABLE_EXISTS_ACTION の使い分け(SKIP / REPLACE / APPEND / TRUNCATE)
- NETWORK_LINK で DB 間を直接転送する方法
- 進捗の確認と実行中ジョブの操作(KILL_JOB など)
DIRECTORY オブジェクトの作成と権限付与
Data Pump でエクスポートやインポートを実行するには、Oracle が認識できる DIRECTORY オブジェクトが必要です。DIRECTORY はサーバー上の OS ディレクトリへのエイリアスで、DBA 権限で作成してからユーザーに READ / WRITE 権限を付与します。
-- DBA 権限でログインして DIRECTORY を作成する CREATE DIRECTORY dp_dir AS '/u01/backup/datapump'; -- ※ ディレクトリは OS 上に実際に存在する必要がある(Oracle は自動作成しない) -- DIRECTORY 一覧を確認する SELECT directory_name, directory_path FROM DBA_DIRECTORIES ORDER BY directory_name; -- ユーザーに READ / WRITE 権限を付与する GRANT READ, WRITE ON DIRECTORY dp_dir TO hr; GRANT READ, WRITE ON DIRECTORY dp_dir TO scott; -- Oracle にはデフォルトで DATA_PUMP_DIR が存在する(環境による) -- パスは SELECT * FROM DBA_DIRECTORIES WHERE directory_name='DATA_PUMP_DIR'; で確認
expdp でエクスポートする
expdp はコマンドラインから実行する OS コマンドです(SQL*Plus ではない)。基本的なパラメータと組み合わせて、スキーマ・テーブル・データベース全体のエクスポートができます。
# スキーマ単位でエクスポート(最も一般的な使い方) expdp hr/hr_password@localhost:1521/orcl SCHEMAS=hr DIRECTORY=dp_dir DUMPFILE=hr_schema_%date%.dmp LOGFILE=hr_export.log # 複数スキーマをまとめてエクスポート expdp system/password@orcl SCHEMAS=hr,scott,oe DIRECTORY=dp_dir DUMPFILE=multi_schema_%U.dmp FILESIZE=2G PARALLEL=4 LOGFILE=multi_schema_export.log # 特定テーブルだけをエクスポート expdp hr/hr_password@orcl TABLES=hr.employees,hr.departments DIRECTORY=dp_dir DUMPFILE=emp_dept.dmp LOGFILE=emp_dept_export.log # データベース全体(フルエクスポート) expdp system/password@orcl FULL=y DIRECTORY=dp_dir DUMPFILE=full_%U.dmp FILESIZE=5G PARALLEL=8 LOGFILE=full_export.log # PARFILE(パラメータファイル)を使う場合 expdp system/password@orcl PARFILE=/home/oracle/export.par # /home/oracle/export.par の内容: # SCHEMAS=hr # DIRECTORY=dp_dir # DUMPFILE=hr_%U.dmp # LOGFILE=hr_export.log # COMPRESSION=ALL # PARALLEL=4
-- QUERY: 特定の条件でデータを絞り込んでエクスポートする
-- ※ テーブル単位で条件を指定する(スキーマエクスポート時は対象テーブルを指定)
-- コマンドライン: QUERY=hr.employees:"WHERE department_id=60"
-- PARFILE 内:
-- QUERY=hr.employees:"WHERE hire_date > DATE '2020-01-01'"
-- EXCLUDE: 特定のオブジェクト種類・オブジェクトをエクスポートから除外する
-- コマンドライン例(PARFILE 推奨):
-- EXCLUDE=STATISTICS -- オプティマイザ統計を除外(インポート後に収集する)
-- EXCLUDE=GRANT -- 権限を除外
-- EXCLUDE=TABLE:"='TEMP_LOG'" -- 特定テーブルを除外
-- EXCLUDE=INDEX -- すべてのインデックスを除外(再作成するケース)
-- INCLUDE: 特定のオブジェクトだけをエクスポートする
-- INCLUDE=TABLE:"IN ('EMPLOYEES','DEPARTMENTS')"
-- INCLUDE=PROCEDURE
-- INCLUDE=TABLE,INDEX -- テーブルとインデックスのみ
-- CONTENT: エクスポートする内容を選択する
-- CONTENT=ALL -- データとメタデータ(デフォルト)
-- CONTENT=DATA_ONLY -- データのみ(DDLなし)
-- CONTENT=METADATA_ONLY -- 定義のみ(データなし)
impdp でインポートする
インポートは expdp と同じ構文を使います。移行先のスキーマ名や表領域名が異なる場合は REMAP_SCHEMA と REMAP_TABLESPACE で変換できます。
# 同じスキーマ名でインポート(最もシンプル) impdp hr/hr_password@localhost:1521/orcl_dev SCHEMAS=hr DIRECTORY=dp_dir DUMPFILE=hr_schema.dmp LOGFILE=hr_import.log # スキーマ名を変えてインポート(本番 hr → 開発 hr_dev) impdp system/password@orcl_dev REMAP_SCHEMA=hr:hr_dev DIRECTORY=dp_dir DUMPFILE=hr_schema.dmp LOGFILE=hr_import_remap.log # 表領域名も変えてインポート(本番 USERS → 開発 USERS_DEV) impdp system/password@orcl_dev REMAP_SCHEMA=hr:hr_dev REMAP_TABLESPACE=USERS:USERS_DEV,INDX:INDX_DEV DIRECTORY=dp_dir DUMPFILE=hr_schema.dmp LOGFILE=hr_import_remap.log # テーブル単位でインポート impdp hr/hr_password@orcl_dev TABLES=hr.employees DIRECTORY=dp_dir DUMPFILE=emp_dept.dmp TABLE_EXISTS_ACTION=REPLACE LOGFILE=emp_import.log # フルインポート(新規 DB へのリストア) impdp system/password@new_orcl FULL=y DIRECTORY=dp_dir DUMPFILE=full_%U.dmp PARALLEL=8 LOGFILE=full_import.log
-- TABLE_EXISTS_ACTION: インポート先にテーブルが存在する場合の動作
-- SKIP : 既存テーブルをスキップ(デフォルト。データを追加しない)
-- APPEND : 既存テーブルにデータを追記する(制約チェックあり)
-- TRUNCATE: 既存テーブルを TRUNCATE してからインポート(注意: TRUNCATE は ROLLBACK 不可)
-- REPLACE : 既存テーブルを DROP して再作成してインポート
-- TRANSFORM: インポート時に DDL を変換する
-- TRANSFORM=SEGMENT_ATTRIBUTES:N -- ストレージ句・表領域指定を除去(REMAP_TABLESPACE と競合する場合に使う)
-- TRANSFORM=OID:N -- Object ID を再生成する(オブジェクト型・XMLType 使用時)
-- SQLFILE: 実際にインポートせず、実行される DDL を SQL ファイルに出力する(ドライラン)
-- impdp system/password@orcl DIRECTORY=dp_dir DUMPFILE=hr.dmp SQLFILE=dp_dir:hr_ddl.sql
-- EXCLUDE=STATISTICS: インポート後に DBMS_STATS で統計を収集するためエクスポートデータの統計を無視する
-- (インポート完了後: EXEC DBMS_STATS.GATHER_SCHEMA_STATS('HR'); で最新統計を収集)
NETWORK_LINK で DB 間を直接転送する
NETWORK_LINK を使うと、ダンプファイルを介さずに直接 DB 間でデータを転送できます。本番環境から開発環境への定期コピーや、DB 移行時に便利です。転送元 DB に対して Database Link が設定されている必要があります。
-- 転送先 DB(import を実行する DB)側で DB Link を作成する
CREATE DATABASE LINK prod_link
CONNECT TO hr IDENTIFIED BY hr_password
USING 'prod_db'; -- tnsnames.ora のエントリ名または Easy Connect 文字列
-- DB Link の接続テスト
SELECT * FROM dual@prod_link;
-- NETWORK_LINK を使ったインポート(転送先 DB で実行)
-- ※ expdp/impdp ではなく impdp に NETWORK_LINK を指定する
-- コマンドライン:
-- impdp hr/hr_password@dev_db -- SCHEMAS=hr -- NETWORK_LINK=prod_link -- REMAP_SCHEMA=hr:hr_dev -- DIRECTORY=dp_dir -- LOGFILE=network_import.log
-- ※ NETWORK_LINK 使用時は DUMPFILE が不要(直接転送)
-- ※ 転送元(prod_db)に DATAPUMP_EXP_FULL_DATABASE 権限またはスキーマ権限が必要
-- DBMS_DATAPUMP を使って PL/SQL からジョブを制御する場合の例
DECLARE
h NUMBER;
BEGIN
h := DBMS_DATAPUMP.OPEN(
operation => 'EXPORT',
job_mode => 'SCHEMA',
job_name => 'HR_EXPORT_JOB',
remote_link => NULL,
version => 'COMPATIBLE'
);
DBMS_DATAPUMP.ADD_FILE(h, 'hr_export.dmp', 'DP_DIR');
DBMS_DATAPUMP.ADD_FILE(h, 'hr_export.log', 'DP_DIR', filetype => DBMS_DATAPUMP.KU$_FILE_TYPE_LOG_FILE);
DBMS_DATAPUMP.METADATA_FILTER(h, 'SCHEMA_EXPR', 'IN (''HR'')');
DBMS_DATAPUMP.START_JOB(h);
DBMS_DATAPUMP.DETACH(h); -- バックグラウンドで実行してデタッチ
END;
/
進捗の確認と実行中ジョブの操作
-- 実行中の Data Pump ジョブを確認する
SELECT job_name, operation, job_mode, state, degree, attached_sessions
FROM DBA_DATAPUMP_JOBS
WHERE state = 'EXECUTING';
-- 進捗を確認する(V$SESSION_LONGOPS)
SELECT sid, serial#, opname, sofar, totalwork,
ROUND(sofar / NULLIF(totalwork, 0) * 100, 1) AS pct_done,
elapsed_seconds, time_remaining
FROM V$SESSION_LONGOPS
WHERE opname LIKE 'Data Pump%'
AND totalwork > 0
ORDER BY start_time DESC;
-- 実行中ジョブに対話的に接続する(別ターミナルから)
-- expdp attach=<job_name>
-- 接続後の操作:
-- STATUS : 現在の進捗を表示
-- PARALLEL=8 : 並列度を変更する(実行中に変更可能)
-- KILL_JOB : ジョブを強制終了してダンプファイルを削除する
-- STOP_JOB : ジョブを停止する(後で再開可能)
-- START_JOB: 停止したジョブを再開する
-- EXIT_CLIENT: Data Pump インターフェースを抜ける(ジョブはバックグラウンドで継続)
-- 残ったジョブメタデータをクリーンアップする(失敗後など)
DROP TABLE hr.SYS_EXPORT_SCHEMA_01 PURGE; -- ジョブ制御テーブルの削除
-- ※ テーブル名は DBA_DATAPUMP_JOBS.job_name に対応する
よくあるエラーと対処法
| エラー | 原因 | 対処法 |
|---|---|---|
| ORA-39002: invalid operation | DIRECTORY 権限がない・DIRECTORY が存在しない | GRANT READ, WRITE ON DIRECTORY を確認する。DBA_DIRECTORIES で DIRECTORY の存在を確認する |
| ORA-39070: unable to open the log file | DIRECTORY の OS パスに書き込み権限がない | OS 側のディレクトリに oracle ユーザーの書き込み権限があるか確認する |
| ORA-39166: object not found | EXCLUDE/INCLUDE で指定したオブジェクト名が存在しない | オブジェクト名の大文字小文字と存在を USER_OBJECTS で確認する |
| ORA-31626: job does not exist | ATTACH で接続しようとしたジョブが存在しない | DBA_DATAPUMP_JOBS で正確なジョブ名を確認する |
| ORA-39127: unexpected error encountered in call to export_string | 統計データのエクスポートでメモリ不足など | EXCLUDE=STATISTICS を追加してエクスポートし、インポート後に DBMS_STATS で収集する |
| インポート時の ORA-00959: tablespace not found | エクスポート元の表領域がインポート先に存在しない | REMAP_TABLESPACE=元:先 で変換するか、インポート先に同名表領域を作成する |
よく使うパラメータ一覧
| パラメータ | 説明 | 例 |
|---|---|---|
| SCHEMAS | エクスポート/インポートするスキーマ名(カンマ区切り) | SCHEMAS=hr,scott |
| TABLES | テーブル単位の指定(スキーマ.テーブル名) | TABLES=hr.employees |
| FULL | フルデータベースのエクスポート/インポート | FULL=y |
| DIRECTORY | ダンプファイル・ログファイルの出力先 DIRECTORY 名 | DIRECTORY=dp_dir |
| DUMPFILE | ダンプファイル名(%U で連番、%date% は OS 依存) | DUMPFILE=hr_%U.dmp |
| LOGFILE | ログファイル名 | LOGFILE=hr_export.log |
| PARALLEL | 並列度(Enterprise Edition のみ) | PARALLEL=4 |
| COMPRESSION | 圧縮(METADATA_ONLY / DATA_ONLY / ALL / NONE) | COMPRESSION=ALL |
| FILESIZE | ダンプファイルの最大サイズ(分割する場合は %U も指定) | FILESIZE=2G |
| FLASHBACK_TIME | 指定時刻のデータをエクスポートする(一貫したスナップショット) | FLASHBACK_TIME=SYSTIMESTAMP |
| REMAP_SCHEMA | スキーマ名を変換してインポート(impdp のみ) | REMAP_SCHEMA=hr:hr_dev |
| REMAP_TABLESPACE | 表領域名を変換してインポート(impdp のみ) | REMAP_TABLESPACE=USERS:USERS_DEV |
| TABLE_EXISTS_ACTION | 既存テーブルの扱い(impdp のみ) | TABLE_EXISTS_ACTION=REPLACE |
| EXCLUDE / INCLUDE | オブジェクト種類・名前でフィルタリング | EXCLUDE=STATISTICS |
| CONTENT | エクスポート内容(ALL / DATA_ONLY / METADATA_ONLY) | CONTENT=DATA_ONLY |
| NETWORK_LINK | DB Link 経由の直接転送(ダンプファイル不要) | NETWORK_LINK=prod_link |
まとめ
- DIRECTORY オブジェクト:Data Pump はサーバーサイドで動作する。ダンプファイルの出力先はクライアント側ではなく、DBA_DIRECTORIES で管理される OS ディレクトリ。GRANT READ, WRITE で各ユーザーに権限を付与する
- expdp の基本:SCHEMAS=スキーマ名 でスキーマ全体をエクスポート。QUERY で行フィルタリング、EXCLUDE=STATISTICS でインポート後に統計を再収集するのが一般的なベストプラクティス
- impdp のスキーマ移行:REMAP_SCHEMA=元:先 でスキーマ名を変更、REMAP_TABLESPACE=元:先 で表領域名を変更。SQLFILE オプションでドライランして DDL を事前確認できる
- TABLE_EXISTS_ACTION:既存テーブルがある場合の動作。SKIP(デフォルト)・APPEND(追記)・TRUNCATE(切り詰め再投入)・REPLACE(DROP→再作成)から選択する
- NETWORK_LINK:DB Link を経由してダンプファイルなしで DB 間を直接転送できる。本番→開発のデータ同期に便利
- 進捗確認:V$SESSION_LONGOPS で進捗率と残り時間を確認。expdp attach=ジョブ名 で実行中ジョブに接続してリアルタイムに操作できる
エクスポートしたデータの整合性確認には SCN(System Change Number)を活用できます。FLASHBACK_TIME や FLASHBACK_SCN で一貫した時点のデータをエクスポートする方法は Oracle SCN 完全ガイドを参照してください。SQL*Loader(sqlldr)を使ったデータロードは Oracle SQL*Loader 完全ガイドも参照してください。