1. 19c expdp 导出慢的真实场景:15G 数据跑了 10 多分钟
先说结论:如果你在 19c 上跑 expdp,发现导出速度比 11g 时代慢了好几倍,而且并行度参数加了跟没加一样,大概率不是你的参数写错了,而是撞上了 Data Pump 的已知 Bug。
我最近帮一个朋友排查过类似的问题。他们的系统还没正式上线,业务负载几乎为零,按理说导出 15G 数据应该是几分钟的事,结果硬生生跑了 10 多分钟。这种「硬件没瓶颈、负载没压力、就是慢」的情况,最让人抓狂。
排查思路其实不复杂。既然业务负载接近 0,那 AWR 报告里 TOP SQL 部分就会非常干净,谁在耗时间一目了然。打开问题时间段的 AWR,果然在 TOP SQL 里看到一条语句执行了 928 次,单次 0.74 秒,累计 689 秒——这个数字和客户反馈的导出总时长基本吻合。再看调用模块,正是 Data Pump Worker。
顺着 SQL ID 找到 SQL 文本,内容是查询v_$open_cursor视图:
SELECT COUNT(*) FROM sys.v_$open_cursor WHERE sid = SYS_CONTEXT('USERENV', 'SID') AND cursor_type = 'OPEN_PLSQL';这条语句本身没毛病,但它被 Data Pump Worker 高频调用,就成了性能杀手。根因是 Oracle Bug 28771564,影响 12.2.0.1 以上版本,在 20.1 才修复。19c 正好在受影响范围内。
所以这篇文章不只是讲一个 Bug,而是给你一套完整的排查清单:从 expdp 参数模板、并行度为什么不生效、日志怎么比对,到用 TaoToken 统一 Key 管理多工具调用。你可以直接照着操作。
2. TaoToken 前置准备:统一 Key 管理多工具调用
在讲参数之前,先解决一个实际问题:排查 Data Pump 的时候,你往往需要同时调用多个工具——比如用 AI 助手分析 AWR 报告、查 MOS 文档、生成排查脚本。每个工具都要单独配 Key、单独管额度,时间一长就乱。
TaoToken 做的就是这件事:一个 Key 打通多个模型和工具调用。官网入口在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,你可以先去核对一下当前支持的模型列表和接入方式。
具体来说,你需要准备三样东西:
Base URL:https://taotoken.net/api(注意这个地址不加 UTM 参数,直接用于 API 调用)
API Key:在控制台创建,地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,创建后复制保存。
Model ID:根据你要用的模型填写,比如claude-sonnet-4-20250514或gpt-4o这类。具体可用的 Model ID 在文档里查:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite
如果你用的是 Claude Code 做代码辅助,接入方式略有不同,参考这个地址:https://taotoken.net/ClaudeCodeAnthropic?utm_source=taotoken_aicg_blog_end&utm_content=ClaudeCodeAnthropic&utm_campaign=rewrite
为什么要先讲这个?因为后面排查 Bug 的时候,你需要快速查文档、比对补丁号、生成测试脚本。如果每个环节都卡在「Key 在哪、额度够不够」上,效率就没了。统一 Key 之后,你可以在一个地方管理所有调用。
注意:TaoToken 是 API 聚合服务,不是数据库工具,也不替代任何编辑器。它的作用是让你在排查过程中调用模型能力更顺手。
3. 可复制配置:expdp 并行与压缩参数模板
现在进入正题。先给你一份可以直接改改就用的 expdp 参数模板,然后解释每个参数为什么这么设。
3.1 基础并行导出模板
expdp system/your_password@orclpdb \ directory=DATA_PUMP_DIR \ dumpfile=exp_%U.dmp \ logfile=exp_full.log \ schemas=YOUR_SCHEMA \ parallel=4 \ filesize=2G \ compression=ALL \ compression_algorithm=MEDIUM \ metrics=Y \ logtime=ALL几个关键点:
parallel=4不是随便写的。并行度应该和你的 CPU 核心数、I/O 吞吐能力匹配。一般建议设为 CPU 核心数的 1/2 到 2/3。设太高反而会因为资源争抢变慢。
filesize=2G配合dumpfile=exp_%U.dmp使用,%U是通配符,会生成 exp_01.dmp、exp_02.dmp 这样的文件。每个文件 2G,方便传输和并行写入。
compression=ALL会压缩数据和元数据。如果 CPU 资源紧张,可以改成compression=DATA_ONLY,只压缩数据。
metrics=Y和logtime=ALL是排查利器。前者在日志里输出详细的执行统计,后者给每行日志加时间戳。后面比对日志就靠它们。
3.2 针对 Bug 28771564 的规避配置
如果你确认环境受 Bug 影响但暂时打不了补丁,可以试试这个组合:
expdp system/your_password@orclpdb \ directory=DATA_PUMP_DIR \ dumpfile=exp_%U.dmp \ logfile=exp_full.log \ schemas=YOUR_SCHEMA \ parallel=2 \ filesize=2G \ compression=ALL \ metrics=Y \ logtime=ALL \ exclude=STATISTICSexclude=STATISTICS可以减少元数据导出时的额外查询。parallel=2是保守值,因为 Bug 会导致并行 Worker 频繁查询v_$open_cursor,并行度越高,这个查询被调用的次数越多,反而拖慢整体速度。
3.3 用 JSON 管理多环境配置
如果你有多个数据库环境要导出,建议用 JSON 文件管理参数,避免每次手敲:
{ "prod": { "connect": "system/password@prod_pdb", "directory": "DATA_PUMP_DIR", "parallel": 4, "compression": "ALL", "filesize": "2G", "metrics": "Y", "logtime": "ALL" }, "test": { "connect": "system/password@test_pdb", "directory": "DATA_PUMP_DIR", "parallel": 2, "compression": "DATA_ONLY", "filesize": "1G", "metrics": "Y", "logtime": "ALL" } }然后写个简单的 shell 脚本读取 JSON 拼命令。这样切换环境只需要改一个字段。
3.4 检查并行度是否真的生效
很多人以为加了parallel=4就真的并行了,其实不一定。用下面这条 SQL 查实际运行的 Worker 数量:
SELECT sid, serial#, degree, state, event FROM v$px_process WHERE sid IN ( SELECT sid FROM v$session WHERE module LIKE 'Data Pump%' );如果degree列显示的是 1,说明并行没生效。常见原因有三个:一是 dumpfile 只写了一个文件,没有用%U;二是 filesize 没设,所有数据写一个文件;三是表本身没有分区,Data Pump 无法拆分。
4. 验证请求与成功结果:日志比对方法
参数配好了,怎么确认真的变快了?不能只看「感觉快了」,要有数据支撑。
4.1 用 logtime 做时间线比对
logtime=ALL会在日志每行前面加时间戳。导出完成后,直接看日志开头和结尾的时间差:
head -5 exp_full.log tail -5 exp_full.log对比两次导出的日志,重点看这几个阶段的时间:
- 「Starting "SYSTEM"."SYS_EXPORT_SCHEMA_01"」到「Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA」之间的时间,这是元数据解析阶段。
- 「. . exported "SCHEMA"."TABLE_NAME"」每张表的导出耗时。
- 「Job "SYSTEM"."SYS_EXPORT_SCHEMA_01" successfully completed」的总耗时。
如果元数据解析阶段从 300 秒降到 30 秒,说明 Bug 规避生效了。
4.2 用 metrics=Y 看详细统计
metrics=Y会在日志末尾输出类似这样的统计:
Total estimation time: 00:00:05 Total execution time: 00:04:32这个Total execution time就是实际导出耗时。你可以把它和 AWR 里的 Data Pump Worker 耗时做交叉验证。
4.3 用 AWR 确认 TOP SQL 变化
导出前后各采一次 AWR,对比 TOP SQL 里v_$open_cursor那条语句的执行次数。如果从 928 次降到个位数,说明问题解决了。
SELECT sql_id, executions, elapsed_time/1000000 AS elapsed_sec FROM dba_hist_sqlstat WHERE sql_id = 'dqpwrs34cbf54' AND snap_id BETWEEN &begin_snap AND &end_snap;4.4 用 TaoToken 辅助分析日志
如果你不想手动比对,可以把日志内容贴给模型分析。用 TaoToken 的模型对话接口:
curl -X POST https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer YOUR_TAOTOKEN_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-4-20250514", "messages": [ {"role": "user", "content": "对比这两份 expdp 日志,找出耗时差异最大的阶段:\n日志A:...\n日志B:..."} ] }'模型对话入口在 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite ,你也可以直接在网页上操作。
5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth
排查过程中最容易卡在几个报错上。我按实际遇到的频率排个序。
5.1 401 Unauthorized
这个最常见。原因通常是 Key 没填对、Key 过期、或者 Base URL 写错了。
检查清单:
- Base URL 是不是
https://taotoken.net/api,注意结尾没有多余的斜杠。 - Key 是不是从控制台复制完整了,有没有多空格。
- 请求头是不是
Authorization: Bearer YOUR_KEY,Bearer 后面有一个空格。
如果你用的是 Claude Code 接入,OAuth 流程走完后如果还报 401,检查一下 settings 文件里的配置:
{ "apiKey": "YOUR_TAOTOKEN_KEY", "baseUrl": "https://taotoken.net/api", "model": "claude-sonnet-4-20250514" }三件套缺一不可:Base URL、Key、Model ID。
5.2 local proxy failed
这个报错通常出现在你本地配了代理但代理没启动,或者代理地址写错了。如果你没有用代理,检查环境变量里有没有残留的HTTP_PROXY或HTTPS_PROXY:
echo $HTTP_PROXY echo $HTTPS_PROXY unset HTTP_PROXY unset HTTPS_PROXY清掉之后重试。
5.3 reading choices 相关报错
这个一般出现在流式响应解析时。如果你用 curl 测试,确保加了-N参数禁用缓冲:
curl -N -X POST https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"gpt-4o","messages":[{"role":"user","content":"test"}],"stream":true}'如果是代码里报reading choices,检查你的 JSON 解析逻辑是不是按流式格式处理的。非流式响应里choices是数组,流式响应里每个 chunk 的choices也是数组但结构不同。
5.4 Codex auth.json 配置问题
如果你用 Codex 类工具,auth.json 的路径和格式要对:
{ "openai": { "apiKey": "YOUR_TAOTOKEN_KEY", "baseURL": "https://taotoken.net/api" } }文件放在~/.codex/auth.json。改完之后重启工具。
5.5 expdp 本身的报错
如果 expdp 报ORA-39001: invalid argument value,检查参数名有没有拼错。19c 里compression_algorithm的值只能是BASIC、LOW、MEDIUM、HIGH,写错了会报这个。
如果报ORA-39095: Dump file space has been exhausted,说明 dumpfile 空间不够,加大 filesize 或者清理目录。
6. 语义一致 CTA:把 Key 和补丁一起管起来
回到最开始的问题:19c 下 expdp 慢,根因是 Bug,解法是打补丁加调参。但整个排查过程中,你还需要查文档、比对日志、生成脚本,这些环节如果各自为政,效率就上不去。
TaoToken 在这里的角色是统一入口。一个 Key 管住所有模型调用,不用在多个平台之间切换。具体来说:
查补丁信息、比对 MOS 文档,用模型对话:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite
生成排查脚本、分析 AWR 输出,用 Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite
管理 Key 和额度,去控制台:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite
创建新的 API Key:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite
核对接入方式:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite
最后提醒一句:Bug 28771564 只是 19c Data Pump 众多已知问题中的一个。Oracle 专门出了 Doc ID 2819284.1 列出 19.10 以上版本推荐的主动性补丁。比如 19.22 版本的 Merge Patch 36092868 修复了 172 个 Bug。建议你核查自己的环境版本,该打的补丁打上,比事后调参省事得多。
几个和性能直接相关的 Bug 号记一下:28771564(v_$open_cursor 高频查询)、26565187(12.2 导出变慢)、32370367(19.7 比 11.2.0.4 慢三倍)、32421259(大库导出耗时过长)、31668026(estimate=blocks 被忽略)。拿着这些号去 MOS 查,比盲目试参数快得多。