expdp 报错:ora-22923 amount of data specified in streaming LOB write is 0

本文详细阐述了在使用Oracle expdp工具导出数据时遇到的ORA-22923错误,该错误指出在尝试通过流式机制写入LOB字段时,输入的数据量被指定为0,导致无法正确处理长RAW类型字段中的空值。通过创建自定义函数检查长RAW字段的长度,并在导出过程中跳过长度为0的记录,最终成功解决了问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一客户让我看下一个expdp的导出错误,信息如下(表名已处理):

ora-31693 :table data object xx.xxxx failed to load/unload and is being skipped  due to error;

ora-29913 :error in executing ODCIEXTTABLEPOPULATE callout

ora-22923 :amount of data specified in streaming LOB write is 0


用oerr ora 22923 在操作系统上看了下oracle给的建议:

Cause: Trying to write LOB value via the streaming mechanism (i.e. unlimited write) but the input amount of data to stream was specified as 0. Thus, the user is trying to write 0 bytes to the LOB value.
Action: Write more than 0 bytes to the LOB value.

意思是不能朝lob字段里面写入零字节,该表上有个long raw类型的字段,这个已经被oracle淘汰的字段总是让人烦恼。

现在我怀疑该字段中可能存在空值的情况,但long raw字段又不支持谓词where的查询,所以无法定位到哪条记录存在空值。。。(也许这个可以作为切入点,来定位是否是空值,然而进一步删除该空值的情况)

在metalink上找了半天,也没有找到符合错误描述的文档,有点无奈。更多看到的都是建议将long换成lob型,但客户这边的这套系统是基于8i开发的,历史遗留问题总是难以解决的。

现在客户想要清理这张带有long raw字段表的部分数据,数据量很大,想利用expdp/impdp的方式来做,但总是报出如上错误,我这边又找不到好的方法,也不能确认是不是某个未公开的bug,只好像metalink所说的那样,建议选用exp/imp的方式来做了。客户勉强能接受,但对速度方面,还是有很多顾虑 。


倒是头一次遇到这样的情况,情绪有点低落啊,毕竟问题没有圆满解决。客户这边又因为牵一发而动全身的缘故,不能改动表结构。

我再找找看,以期获得某意外之喜,或某些灵感。


------------------------------------------------------------------------2015-03-31  续,问题不解决,寝食难安啊-------------------------------------------------------------------------

之前一直陷入了如何解决这个ora问题的思路陷阱里面,突然意识的,我完全可以跳过该ora错误,既然oracle expdp不支持0字节的lob导出,那么我就找出那条0字节的数据,在metalink上找了查找long raw字段大小的方法,贴在下面:


create or replace function lr_length( p_rowid in rowid ) return 
number 
as 
l_raw long raw; 
begin 
select name into l_raw 
from expdptest 
where rowid = p_rowid; 
if ( l_raw is null ) then 
return null; 
else 
return utl_raw.length(l_raw); 
end if; 
exception 
when others then return NULL; 
end;
/


select rowid, lr_length( rowid ) len from expdptest ;


后来执行结果验证了我先前的猜测,果然存在一条long raw类型字段值为null的情况,和业务商量,建议在expdp的时候跳过该值,expdp导出成功。

<think>嗯,用户遇到了Oracle 19c中使用expdp导出数据时出现的ORA-39002、ORA-39070ORA-29283错误组合。这类错误通常与目录权限或文件系统问题相关,需要系统性地排查。 先看错误链的逻辑关系:ORA-39002是操作无效的通用提示,ORA-39070说明无法打开日志文件,而ORA-29283指向具体的文件操作权限问题。核心应该聚焦在第三个错误上。 根据引用[1]的案例,用户环境是Windows系统(从路径C:\Users可见),这提示要特别注意Windows特有的权限机制。需要重点检查: 1. 目录对象实际路径的NTFS权限,需确保Oracle服务运行账户(通常是LocalSystem或指定域账户)有完全控制权 2. 防病毒软件实时扫描可能锁定文件,可尝试临时禁用测试 3. 路径是否存在空格或特殊字符(如示例中的%U),虽然expdp支持%U但最好先用简单文件名测试 引用[2][3]提到的ORA-31626/31634错误虽然不同,但说明job管理问题也可能与目录权限相关,侧面印证权限问题的普遍性。不过当前用户未出现这些错误,暂时不作为重点。 具体排查步骤需要分层进行:首先验证目录对象配置,用SQL查询确认路径映射正确;然后检查操作系统权限,特别是Oracle进程的写权限;最后测试实际写入能力,比如用utl_file包直接写文件测试。 考虑到用户是DBA身份,解决方案中需要包含具体操作命令: - 查询目录对象的SQL:select * from dba_directories - 重建目录的DDL:create or replace directory... - 权限授予语句:grant read, write on directory... 同时要提醒易忽略点:云环境或集群中可能涉及多个节点的权限同步问题,以及Windows UAC虚拟化导致的实际路径重定向问题(如ProgramData目录的虚拟存储)。 补充的预防措施也很重要,比如设置专用导出目录避免使用临时路径,规范目录命名避免特殊字符等。最后建议用户用最小化测试案例(单文件导出)验证,比直接处理复杂任务更高效。</think>好的,我们来详细分析 Oracle 19c 中使用 `expdp` 导出数据库时遇到的 `ORA-39002`, `ORA-39070`, `ORA-29283` 错误组合,并提供故障排除步骤。 **核心问题分析:** 这组错误的核心通常在于 **Data Pump 无法写入指定的日志文件(或转储文件)**。错误链的含义如下: 1. **ORA-39002: invalid operation**: 这是一个通用的错误,表明 Data Pump 操作失败。它本身不指明具体原因,而是由后续的错误提供细节。 2. **ORA-39070: Unable to open the log file.**: 明确指出 Data Pump 无法打开(通常是为了写入指定的日志文件 (`logfile=ccenseecard_export.log`)。这是问题的直接表现。 3. **ORA-29283: invalid file operation**: 这是最关键的底层错误。它表示操作系统级别的文件操作失败。具体原因需要结合上下文,但最常见于: * **目录权限不足:** Oracle 软件运行用户(通常是 `oracle` 用户或 `dba` 组)对操作系统上 `DIRECTORY` 对象指向的实际物理目录**没有写权限**。 * **目录不存在:** `DIRECTORY` 对象指向的操作系统物理路径不存在。 * **磁盘空间不足:** 目标磁盘或文件系统没有足够的空间来创建或写入日志文件(或转储文件)。 * **路径错误:** `DIRECTORY` 对象定义错误,或者 `dumpfile`/`logfile` 参数中指定的路径无效(例如,包含了操作系统不允许的字符或格式)。 * **文件已存在且不可覆盖:** 如果日志文件已经存在,并且 Oracle 进程没有覆盖它的权限(或者使用了 `REUSE_DUMPFILES=Y` 但文件被其他进程锁定)。 * **文件系统问题:** 文件系统损坏、只读挂载等。 * **SELinux / AppArmor (Linux):** 安全模块阻止了 Oracle 进程对目录的写入访问。 * **防病毒软件锁定:** 防病毒软件可能暂时锁定了文件或目录,阻止写入。 **故障排除步骤:** 1. **验证 `DIRECTORY` 对象:** * 登录到 SQL*Plus (作为有权限的用户,如 `SYS` 或 `SYSTEM`): ```sql SELECT directory_name, directory_path FROM dba_directories WHERE directory_name = 'EXPDP_DIR'; ``` * **检查1:** 确认查询结果中 `EXPDP_DIR` 对应的 `directory_path` 确实是您期望的操作系统目录路径(大小写敏感)。 * **检查2:** 登录到数据库服务器操作系统,检查 `directory_path` 指向的物理路径**是否存在**。使用 `ls -ld ` 命令查看路径是否存在。 * **检查3:** 确认 Oracle 软件运行用户(通常是 `oracle`)对该物理目录拥有**读、写、执行**权限。使用 `ls -ld ` 查看权限,并用 `id` 命令确认当前用户身份(或 `ps -ef | grep pmon` 查看数据库进程的属主)。确保 `oracle` 用户或 `dba` 组有权限。例如: ```bash ls -ld /path/to/expdp_dir # 输出应类似 drwxr-xr-x 或 drwxrwxr-x,且属主/组应为 oracle/dba 或 oracle/oinstall 等。 chmod 775 /path/to/expdp_dir # 如果权限不足,需要修正 (需root或目录所有者) chown oracle:dba /path/to/expdp_dir # 如果所有权不对,需要修正 (需root) ``` 2. **检查磁盘空间:** * 在操作系统上,使用 `df -h` 命令检查 `directory_path` 所在的磁盘分区是否有足够的可用空间。确保空间足够容纳日志文件和预期的转储文件。 3. **检查文件是否存在与权限:** * 在操作系统上,导航到 `directory_path` 指向的目录。 * 检查 `ccenseecard_export.log` 文件是否已经存在: * 如果存在,确认 `oracle` 用户是否有权限覆盖它 (`ls -l ccenseecard_export.log`)。 * 尝试手动删除该文件(如果不需要保留),或者确保 `oracle` 用户有写权限。也可以考虑在 `expdp` 命令中使用不同的 `logfile` 名称测试。 * 尝试在目标目录下用 `oracle` 用户手动创建一个小文件,测试写入权限: ```bash su - oracle # 切换到oracle用户 cd /path/to/expdp_dir touch testfile.txt echo "test" > testfile.txt ls -l testfile.txt rm testfile.txt # 清理测试文件 ``` * 如果手动创建/写入文件失败,说明操作系统权限问题是根本原因,需按步骤1修正目录权限。 4. **简化命令测试:** * 使用最简单的命令排除复杂因素: ```bash expdp system/newECARD2017 directory=EXPDP_DIR dumpfile=test.dmp logfile=test.log schemas=system ``` * 使用更简单的文件名(`test.dmp`, `test.log`)。 * 导出一个小模式(如 `SYSTEM` 本身,或者一个已知存在的小用户模式)。这有助于快速排除磁盘空间问题。 * 如果简化命令成功,说明原始命令中的模式名 (`ccenseecard`) 或文件名格式 (`ccenseecard%U.dmp`) 可能不是问题根源(但文件名格式错误理论上也可能导致问题,简化测试规避了这点)。 5. **检查 Oracle 错误日志:** * 查看数据库的 alert log (`$ORACLE_BASE/diag/rdbms/<dbname>/<instance>/trace/alert_<instance>.log`)。虽然 `expdp` 错误主要记录在它自己的日志文件里(但这次它打不开),但 alert log 有时会捕获到更底层的操作系统交互错误或进程信息。 6. **检查安全模块 (Linux):** * **SELinux:** 检查 SELinux 状态 `sestatus`。如果启用,查看相关审计日志 (`/var/log/audit/audit.log` 或 `ausearch` 命令) 寻找与 `oracle` 进程、`expdp_dir` 路径相关的 `denied` 条目。可能需要调整 SELinux 策略或设置文件上下文 (`chcon`, `semanage fcontext`)。作为临时测试,可尝试 `setenforce 0` 禁用 SELinux(生产环境慎用,测试完需恢复)。 * **AppArmor:** 检查 AppArmor 状态 `aa-status` 和配置文件。可能需要修改 Oracle 相关的 AppArmor 配置文件以允许访问该目录。 7. **检查防病毒软件:** * 临时禁用服务器上的防病毒软件实时扫描功能,然后重试 `expdp` 操作。如果成功,需要在防病毒软件中为 `expdp_dir` 目录添加排除规则。 8. **检查路径格式 (Windows 特别注意):** * 在 Windows 上,确保 `DIRECTORY` 路径使用正确的格式(如 `C:\app\oracle\expdp_dir`),避免使用包含空格或特殊字符的路径(如果必须使用,确保用引号括起来并在 `DIRECTORY` 定义和 `expdp` 命令中一致处理)。确保路径是绝对路径。 * 确认 Oracle 服务(通常是 `OracleServiceORCL` 或 `OracleService`)运行的用户帐户(通常是 `Local System` 或指定域账户)对该目录拥有完全控制权限(右键目录 -> 属性 -> 安全 -> 编辑/添加权限)。 **解决方案总结:** 根据上述排查,最常见的解决方案是: 1. **确保 `DIRECTORY` 对象指向的物理路径存在。** 2. **确保操作系统上的物理目录对 Oracle 运行用户 (`oracle` 或服务账户) 具有 `rwx` (读、写、执行) 权限。** 这是最根本、最常见的原因。 3. **确保目标磁盘有足够空间。** 4. **确保 `logfile` 和 `dumpfile` 指定的文件名合法且无冲突。** 5. **(Linux) 检查并配置 SELinux/AppArmor。** 6. **(Windows) 检查目录权限并确认服务账户权限。** 7. **临时禁用防病毒软件测试。** **示例修正命令 (假设问题在目录权限):** ```sql -- 1. 修正操作系统权限 (以Linux为例, 需root或目录所有者) chown oracle:oinstall /u01/app/oracle/expdp_dir # 修改所有权 chmod 775 /u01/app/oracle/expdp_dir # 修改权限 -- 2. (可选) 如果目录路径错误或不存在,重新创建DIRECTORY对象 (需DBA权限) DROP DIRECTORY expdp_dir; CREATE DIRECTORY expdp_dir AS '/u01/app/oracle/expdp_dir'; -- 使用正确的绝对路径 GRANT READ, WRITE ON DIRECTORY expdp_dir TO system; -- 或所需用户/角色 -- 3. 重新运行简化测试命令 expdp system/newECARD2017 directory=EXPDP_DIR dumpfile=test.dmp logfile=test.log schemas=system ``` **引用参考:** * 引用[1] 提供了具体的错误信息和命令示例,是问题诊断的基础[^1]。 * 引用[2][3] 虽然涉及不同的错误代码 (`ORA-31626`, `ORA-31634`),但强调了目录权限、Job 管理以及与操作系统交互的重要性,其排查思路(如重建组件、检查权限)与本问题有共通之处[^2][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值