ORA 11.2.0.4 执行expdp 导出时报ORA01555错误。
1.执行expdp 导出时报错信息如下
ORA-31693: Table data object "HISCS"."EPR_INPATIENT":"SYS_P144" failed to load/unload
and is being skipped due to error:
ORA-02354: error in exporting/importing data
ORA-01555: snapshot too old: rollback segment number with name "" too small
ORA-22924: snapshot too old
LOB数据不使用UNDO SEGMENT维持读一致性快照。执行DML前,旧的版本在LOB SEGMENT中。
1)访问损坏的LOB段。
2)读取不可用的LOB段的一致性快照。
2.查找损坏的记录
修复方法如下:
1)创建表存储LOB段的信息。
create table corrupt_lobs (corrupt_rowid rowid, err_num number);
2)查看报错的表上哪个字段有CLOB或者BLOB类型。
desc "HISCS"."EPR_INPATIENT";
3)
declare
error_1578 exception;
error_1555 exception;
error_22922 exception;
pragma exception_init(error_1578,-1578);
pragma exception_init(error_1555,-1555);
pragma exception_init(error_22922,-22922);
num number;
begin
for cursor_lob in (
select rowid r, &&lob_column
from &table_owner.&table_with_lob)
loop
begin
num := dbms_lob.instr (cursor_lob.&&lob_column, hextoraw ('889911')) ;
exception
when error_1578 then
insert into corrupt_lobs values (cursor_lob.r, 1578);
commit;
when error_1555 then
insert into corrupt_lobs values (cursor_lob.r, 1555);
commit;
when error_22922 then
insert into corrupt_lobs values (cursor_lob.r, 22922);
commit;
end;
end loop;
end;
/
--提示输入:
Enter value for lob_column : EMP_XML --输入LOB列的列名。
Enter value for table_owner : HISCS --输入表的属主
Enter value for table_with_LOB: EPR_INPATIENT --输入保护LOB字段的表名。
4)查看这个表中显示的损坏的记录。
select * from corrupt_lobs;
3.修复方法
恢复损坏的LOB段。
方法1:物理备份恢复。
方法2:使用SQL语句更新受影响的LOB段。
--即更新为空的BLOB;
update HISCS.EPR_INPATIENT
set <lob column> = empty_blob()
where rowid in (select corrupted_rowid from corrupt_lobs);
commit;
--如果是:BLOB和BFILE 类型的列使用:EMPTY_BLOB()函数更新。
--如果是:CLOB和NCLOB 类型的列使用: EMPTY_CLOB()函数更新。
方法3:
导出时不导出损坏的行。
--如下例子是示例,具体情况需要根据实际情况改。
expdp system/<password> DIRECTORY=my_dir DUMPFILE=expdp_satc.dmp
LOGFILE=expdp_satc.log TABLES=tc.lobdata QUERY=\"WHERE rowid NOT IN \(\'<rowid's listed in corrupt_rowid>\'\)\"
expdp scott/<password> directory=data_pump_dir dumpfile=test.dmp
logfile=test.log tables=EMP
query=\"where rowid not in \(\'AAEWBsAAGAAACewAAC\',\'AAEWBsAAGAAACewAAF\', \'AAEWBsAAGAAACewAAG\'\)\"
exp scott/<password> file=test.dmp log=test.log tables=EMP query=\"where rowid
not in \(\'AAEWBsAAGAAACewAAC\', \'AAEWBsAAGAAACewAAF\',\'AAEWBsAAGAAACewAAG\'\)\"
"
方法4:删除损坏的行。
--需要确认好损坏的具体行。
DELETE FROM HISCS.EPR_INPATIENT WHERE ROWID='XXXXX';
4.总结
LOB段损坏可能引起执行expdp逻辑备份时出现ORA01555快照过旧的问题。对于LOB段来说,旧的版本的数据在LOB段本身里面,而不是在UNDO段里,所以UNDO段里无法构建LOB段一致性快照。由Oracle本身机制引起,理解了这个原因,我们可以通过如上方法修复LOB段的数据或者删除不必要的LOB数据行,待问题修复后再执行导出就万无一失了。