Oracle数据泵(expdp)导出大全:用户/多用户/全库/指定表实战与踩坑

发布时间:2026/9/17 12:30:42
Oracle数据泵(expdp)导出大全:用户/多用户/全库/指定表实战与踩坑 做 Oracle 运维和开发这么多年凡是涉及数据迁移、测试环境搭建、上线前数据归档绕不开一个词——数据泵。开发同事经常甩过来一句话帮我把 xx 库导一下。 但导一下这三个字背后是完全不同的需求是只导某个用户还是多用户一起导是整个库搬走还是只取几张表虽然 expdp 命令看起来只是参数不同但实际踩坑时完全是几套逻辑。这篇文章我把自己这些年用 Oracle 数据泵导出各种范围数据的命令、参数解读、踩坑记录整成了一份可直接参考的笔记。不管你是刚接触数据泵的新手 DBA还是经常要处理数据迁移的开发运维同学应该都能从中找到能直接用的东西。1. 项目背景与技术选型为什么生产环境我坚持用数据泵1.1 数据泵是什么、能解决什么问题数据泵是 Oracle 10g 开始提供的逻辑备份迁移工具命令名是 expdp / impdp最核心的能力就是把数据库中的逻辑对象——表、索引、视图、存储过程、函数、包、序列、触发器、权限、同义词等等——按照你定义的范围导出成一份二进制文件dmp再通过 impdp 导入到另一个环境。它解决的核心问题不是机房宕机了怎么恢复而是如何把一个环境里的数据按需搬到另一个环境。举例来说开发要搭建一套模拟生产的测试环境我不可能把生产服务器的数据文件直接拷过去那样环境差异太大、配置要求也高。更合理的做法是用 expdp 把指定业务用户的数据导出来impdp 导入测试库再配合 remap_schema 把账号、表空间都调整好。这个流程里数据泵是效率最高、官方支持最完善的工具。数据泵适合的场景非常明确数据迁移换服务器、跨平台、跨版本导出后导入新库。环境搭建从生产抽取部分数据到测试、开发环境。数据归档把历史数据或下线业务数据的表单独导出来存档。精细化出数只导某几张表或某个分区给外部系统或数据分析团队用。物理备份做不到这些精细操作。物理备份更像整机镜像数据泵更像按需打包快递两者不是替代关系而是互补关系。1.2 数据泵和 exp、常规物理备份的取舍很多老资料里还在用 exp/imp新手也容易把 expdp 和 exp 混在一起。其实 exp 是老工具Oracle 官方在 10g 之后把精力几乎都放在数据泵上exp 对大数据量、并行、压缩的支持都很弱。我印象里有一次用 exp 导一个几十 GB 的用户跑了七八个小时还没完换成 expdp 开 4 并行一个多小时就结束了差距非常明显。但 expdp 也不是万能的导出文件是私有格式必须配 impdp 用不能像 exp 的二进制文件那样被一些第三方工具读取。数据泵依赖数据库实例运行如果实例挂了、数据库处于 mount 状态expdp 就用不了这时候只能靠 RMAN 物理备份恢复。全库导出时会带出系统 schema、统计信息、目录对象导入时容易出幺蛾子后面我会专门讲怎么规避。所以我的原则很简单逻辑迁移、按需出数用数据泵灾难恢复、整库还原依赖 RMAN 物理备份exp 只在极老版本环境里才会考虑。理清了这个边界后面命令怎么选就不会纠结。1.3 使用数据泵前的整体认知还有一个容易被忽略的点expdp 是服务端工具它虽然看起来是在命令行里执行但实际干活的是数据库后台的作业进程导出的 dmp 文件也只会落在数据库服务器上不是你本地客户端。这个认知错位是很多初学者的第一坑在自己电脑上执行 expdp 命令发现文件没出现在本地就以为失败了。另外数据泵工具不用单独安装数据库装好后就在$ORACLE_HOME/bin目录下跟 sqlplus 是同一个目录。确认版本可以执行expdp -version它会判断客户端版本与数据库版本是否匹配版本差异过大时也会给出提示。理解这些前置概念之后我们就可以把注意力放到真正影响成败的目录、权限和空间上了。2. 动手前不可跳过的准备目录、权限与空间2.1 创建 Directory 对象不是建个文件夹那么简单expdp 的所有 dump 文件都必须落在数据库服务器上由 Directory 对象指定的物理路径中。这个路径是数据库服务器操作系统上的真实目录不是客户端本地目录。不少快速安装环境下默认会有一个 DATA_PUMP_DIR 指向$ORACLE_HOME/rdbms/log之类的目录但大多数情况我们需要自定义。创建方式CREATE OR REPLACE DIRECTORY DATA_PUMP_DIR AS /u01/app/oracle/dump; GRANT READ, WRITE ON DIRECTORY DATA_PUMP_DIR TO SYSTEM;这里两个动作都要做一是数据库里创建目录对象二是确认操作系统上这个目录存在且 Oracle 用户有读写权限。否则即使 expdp 执行了也会报 ORA-39087 目录名无效或者 ORA-29283 文件操作失败。补充一个细节如果目录对象建好后改了操作系统路径记得用CREATE OR REPLACE DIRECTORY重建同时重新授权。查目录对象用SELECT * FROM dba_directories;这个查询在生产环境排查时报错时非常有用能一眼看到目录对象指向的真实路径。2.2 权限清单导出不同范围分别要什么数据泵对权限的要求很多人搞不清。这里有个简单的规律只导出自己 schema 下的对象一般有 CONNECT、RESOURCE 和对象本身的读权限就够但要导别人的 schema、导全库就必须有 EXP_FULL_DATABASE 角色或者具备 DBA 角色。这个角色是官方推荐的数据泵管理权限可以看视图、读所有表、查元数据。生产环境建议不要拿 sys 账号直接跑 expdp每次都创建一个专用账号比如expdp_user授予EXP_FULL_DATABASE和CREATE SESSION就行。这样即使命令被泄露或操作失误影响面也可控。别嫌麻烦我见过很多生产事故就是从拿 sys 跑个导出开始的。network_link模式比较特殊它是在源库建一个到远程库的数据库链接然后直接在本地把远程数据导出来。这种情况需要额外有CREATE DATABASE LINK权限而且远程库要能接受连接。这种模式适合不想在远程服务器上生成文件的场景因为文件直接落在本地库的目录对象里。2.3 空间、字符集、版本的自检清单在写 expdp 命令之前我习惯先做几个快速检查免得命令跑到一半才发现资源不够空间导出文件加上日志体积大约是源数据量的 1 倍左右具体取决于数据可压缩性和是否带索引统计信息。先用下面 SQL 估算大小目标目录留出 1.5 到 2 倍余量SELECT owner, SUM(bytes) / 1024 / 1024 AS MB FROM dba_segments WHERE owner IN (HR, SCOTT) GROUP BY owner;字符集执行SELECT userenv(language) FROM dual;客户端设置 NLS_LANG 和库保持一致。字符集不一致在 expdp 阶段不一定报错但导入后可能出现乱码或 ORA-12899。数据库版本执行SELECT version FROM v$instance;。如果目标库版本比源库低导出时建议加version参数如果目标库版本更高一般不需要。网络传输如果 dmp 文件要通过 FTP/SCP 传输到目标环境记得用二进制模式。文本模式传 dmp 会把文件搞坏这是一个很低级但非常常见的坑。3. 四类导出需求的命令实操与参数解读3.1 导出单个用户最常规的备份迁移动作单用户导出是日常最常用的需求命令最简版本长这样expdp system/****orcl directoryDATA_PUMP_DIR schemashr dumpfilehr_full.dmp logfilehr_full.logschemashr表示导出 hr 用户下的所有对象。dumpfile指定导出文件名logfile指定日志文件名。日志建议必带排障全靠它。这里导出的对象不止是表还有视图、存储过程、函数、包、序列、同义词、触发器、权限等这也是逻辑导出的核心价值——把一个用户的可移植对象整体搬到另一个库依赖关系基本不会丢。如果 hr 表很多、数据量很大可以加并行expdp system/****orcl directoryDATA_PUMP_DIR schemashr dumpfilehr_full_%U.dmp logfilehr_full.log parallel4这里%U是分片文件占位符parallel4会生成多个文件实际文件数量取决于并行度和数据量。注意parallel 大于 1 时dumpfile 一定要带 %U否则大概率遇到 ORA-39095。这是新手最容易踩的坑没有之一。生产环境在线导出还有一个要点——一致性。默认情况下 expdp 在导出过程中其他会话可能还在改数据不同表之间导出的时间点可能不一致。如果业务上需要导出快照一致的数据加上flashback_time或flashback_scnexpdp system/****orcl directoryDATA_PUMP_DIR schemashr dumpfilehr_full_%U.dmp flashback_timeTO_TIMESTAMP(2024-06-01 08:00:00,YYYY-MM-DD HH24:MI:SS)这在 Oracle 11g 以后都很稳定。不过 flashback_time 依赖撤销保留时间如果数据库没有开启足够的 undo_retention可能需要改用 flashback_scn。还有一个小技巧如果只想导表结构、不要数据或者只导数据、不要结构可以用content参数expdp system/****orcl directoryDATA_PUMP_DIR schemashr dumpfilehr_meta.dmp contentmetadata_only expdp system/****orcl directoryDATA_PUMP_DIR schemashr dumpfilehr_data.dmp contentdata_only我在处理超大库时经常把元数据、数据分开导先导元数据、先校验结构再导数据可以避免用一条命令跑到一半才发现对象有问题。3.2 导出多个用户批量处理时逗号和转义是重灾区多用户导出和单用户本质一样只是 schemas 参数里写多个用户逗号分隔expdp system/****orcl directoryDATA_PUMP_DIR schemashr,scott,oe dumpfilemulti_%U.dmp logfilemulti.log parallel4这里最大的坑是逗号和空格。在 Linux shell 里如果写成schemashr, scott, oe空格会导致参数被 shell 拆成多个参数命令会报错或只导出第一个用户。最稳妥的做法是把整个命令写进脚本时用单引号把 schemas 部分包起来或者直接使用 parfile 参数文件。我强烈建议批量导出用 parfile因为到了命令一长、还有 query 条件时shell 的转义真的是灾难。parfile 写法示例文件名比如exp_multi.pardirectoryDATA_PUMP_DIR schemashr,scott,oe dumpfilemulti_%U.dmp logfilemulti.log parallel4 excludestatistics执行命令就清爽很多expdp system/****orcl parfileexp_multi.par多用户导出前我习惯先确认要导哪些用户避免漏导或误导系统用户。可以用SELECT username FROM dba_users WHERE account_status OPEN AND username NOT IN (SYS, SYSTEM, OUTLN, DBSNMP);同时统计每个用户的大小决定是否真要一起导。有些用户几百 GB有些几十 MB混在一起导如果其中一个出问题可能整个作业都会失败。这种情况建议分批次处理先把小用户导完再单独处理大用户。3.3 导出整个数据库fully 的边界与坑全库导出命令expdp system/****orcl directoryDATA_PUMP_DIR fully dumpfilefull_%U.dmp logfilefull.log parallel4一句话fully 不是万能的反而容易踩坑。全库导出默认会把 SYS、SYSTEM 等系统账户的对象也纳入还会导出数据字典、统计信息、目录对象、同义词等。如果源库环境比较复杂全库导出时经常遇到个别对象状态异常导致作业中断。我在某次全库导出中就遇到过一个历史遗留的失效对象导致作业反复报 ORA-31693最后定位到那张表后用 exclude 把它排掉才跑通。所以我的建议是如果所谓整库导出是为了迁移业务数据不要直接 fully更稳妥的是用 schemas 把业务用户全部显式列出来或者用类似写法把系统默认 schema 排掉expdp system/****orcl directoryDATA_PUMP_DIR fully dumpfilefull_%U.dmp excludeSCHEMA:IN (SYS,SYSTEM,ORDSYS,MDSYS)另外在全库导出的场景下对象非常多建议加excludestatistics否则导出文件里会带一堆统计信息导入时这些统计信息可能与目标环境实际情况不符影响执行计划。统计信息可以在导入完成后重新收集不需要跟着数据走。3.4 只导出指定表精细化出数全靠 tables 参数指定表导出是开发问得最多的场景。命令expdp system/****orcl directoryDATA_PUMP_DIR tablesscott.emp,scott.dept dumpfileemp_dept.dmp logfileemp_dept.log几个注意点表名最好带 owner 前缀不带的话默认按当前登录用户匹配很容易出现 ORA-39166 对象未找到。多张表同样要小心逗号和空格问题建议用 parfile。只导某个分区可以用tablesscott.sales:2024_01这种分区语法适合处理大分区表。如果只导出满足条件的数据行加 query 参数expdp system/****orcl directoryDATA_PUMP_DIR tablesscott.emp queryscott.emp:WHERE deptno10 dumpfileemp_dept10.dmp logfileemp_dept10.logquery 在 Linux shell 下容易踩引号坑双引号里套单引号经常被 shell 解析掉。所以我最推荐的方式还是写进 parfile一行一行配置清晰且不用考虑转义。parfile 示例directoryDATA_PUMP_DIR tablesscott.emp,scott.dept queryscott.emp:WHERE deptno10 dumpfiletables_cond.dmp logfiletables_cond.log建议任何带 query 或复杂条件的导出都优先使用 parfile 参数文件不要在 shell 命令行里硬拼引号。指定表导出还可以配合 include/exclude 做更多过滤。比如表非常多但结构上有个共同前缀可以用includeTABLE:LIKE TMP%之类不过通配符在数据泵里写起来有一点绕一般还是建议直接把表名列清楚。4. 导出过程的关键调优与错误排查实录4.1 并行度、压缩与文件分片提速的关键参数数据泵最值钱的能力之一就是并行导出。并行度并不是越大越好它会同时占用 CPU、IO 和 undo 资源生产环境我一般控制在 2 到 8 之间具体要看数据库服务器核数和 IO 能力。如果数据库跑在一个小型虚拟机上开 8 并行反而可能导致磁盘 IO 打满让整个实例变慢。调并行时盯着数据库负载是个好习惯。常用优化参数组合expdp system/****orcl directoryDATA_PUMP_DIR schemashr dumpfilehr_full_%U.dmp logfilehr_full.log parallel4 compressiondata_only filesize4G status300 logtimeallcompressiondata_only只压缩数据部分比compressionall快而且压缩的 CPU 消耗也更低。filesize4G单个 dump 文件超过 4G 就自动开新文件配合 %U避免生成单个超大文件。这在目标文件系统有单文件大小限制时特别重要。status300每 300 秒打印一次进度后台长任务是救命设置。logtimeall日志每行带时间戳排查耗时问题很有用。还有一个实用技巧导出过程中想看作业跑到哪了不要瞎猜查数据泵视图SELECT job_name, state, degree, attached_sessions FROM dba_datapump_jobs;也可以直接用 expdp attach 重新连接后台作业expdp system/****orcl attachHR_FULLattach 时建议先看视图里的完整 job_name再写准确避免连接错作业。如果之前跑过同一文件名的导出重跑之前记得处理同名 dmp或者加reuse_dumpfilesy参数否则命令会停下来问你文件是否覆盖。4.2 导入端的基本配合操作导出不是终点数据泵导出之后一般都要做导入验证尤其是迁移场景。impdp 的常用配套参数我先列一下impdp system/****orcl directoryDATA_PUMP_DIR dumpfilehr_full.dmp schemashr remap_schemahr:hr_test remap_tablespaceusers:ts_test table_exists_actionreplaceremap_schemahr:hr_test把导出文件里的 hr 用户对象导入到 hr_test 用户下。测试环境经常用这个参数避免覆盖原账号。remap_tablespaceusers:ts_test把默认表空间从 users 映射到 ts_test。如果目标库里没有源库同名的表空间导入必报错这个参数就是用来兜底的。table_exists_actionreplace目标表已存在时替换。迁移场景常用但如果目标表有业务数据慎用它会先 drop 再 create。version19跨大版本导入时用。如果源库是 19c目标库是 12c导出时就要加version12.2否则 impdp 可能遇到不兼容对象。经验法则凡是导出的数据都要在目标库里完整导入一遍验证通过这个交付才算完成。有时候导出过程顺利导入却很痛苦问题往往出在权限、表空间和对象依赖上提前在目标环境验证能省很多时间。4.3 常见报错速查表与排查思路下面是我这些年遇到最多的数据泵报错整理成速查表报错信息常见原因解决思路ORA-39002: 无效操作登录账号没有 EXP_FULL_DATABASE 或 DBA 角色或执行了无权限的导出模式给账号授予 EXP_FULL_DATABASE检查导出模式参数ORA-39087: 目录名无效Directory 对象不存在、名字拼写错误或指向的 OS 路径不可访问重建 directory检查 dba_directories确认 OS 权限ORA-31693 / ORA-31617表级导出失败通常伴随前一条 ORA 错误可能是对象损坏、权限不足或 LOB 段异常查看完整日志定位具体对象用 exclude 排除异常表ORA-31626: 作业不存在会话中断、作业被取消或已失败也可能磁盘满导致作业终止查看 dba_datapump_jobs清理磁盘空间重跑作业ORA-39166: 未找到对象tables / schemas 参数中指定的对象或用户不存在或登录账号无权限查看核对对象 owner、名称确认权限ORA-39149: 无法授权登录账号不是 DBA无权对导入对象授权使用有足够权限的账号执行ORA-39095: Dump file space exhausted并行进程写入同一文件导致空间不足或未使用 %U 分片dumpfile 加 %U或增大 filesize或清理磁盘还有一个更经典的真实案例我有一次导全库日志里反复出现 ORA-31693定位到最后是一张表里的 LOB 列所在表空间空间不足expdp 在读取时一直失败。当时不是数据本身的问题而是那个表空间满了、该对象的段分配异常。把它排除后重新导出其他数据都正常。所以遇到 ORA-31693 这类问题时一定要往前翻日志看紧跟在它前面的是什么错误那才是根因。5. 写在最后的几点实操心得5.1 我的保守做法先看源数据再动手每次接到导一下数据的需求不管对方说得多随意我都会先做三件事查一下要导对象的实际大小、确认字符集、确认目标环境版本。如果对方说全库导出我会追问一句是要导所有业务用户还是真要把系统用户也带上绝大多数情况下业务用户就够用了。先元数据、后数据是我处理大库的默认流程。先执行一次contentmetadata_only把架构导出来看一眼也可以拿来快速验证目标环境兼容性然后再导数据。这样万一出问题损失的时间成本也小得多。5.2 给新手的建议从最小可行导出练起如果你是刚接触数据泵不要一上来就全库导出。拿一个测试库建两个测试用户、几张表、几行数据从schemas用户1开始练然后试多用户、指定表、query 条件最后跑一遍导入。每跑一次就去看日志、看 dmp 文件的大小和内容结构。等这几个场景都熟练了再上生产处理真数据。数据泵这个工具虽然命令不算多但参数之间的配合和报错的语义确实需要时间积累。我自己做数据库这个行当这么多年最大的感受就是导出只是数据搬运的一半导入验证、权限规划、空间预估、一致性保证这些看不见的功夫才是项目中真正拉开差距的地方。希望这份笔记能帮你少走一些弯路尤其是在 Oracle 数据泵导出各种范围数据的场景里做到心里有数、手上不慌。