容易在导出时遇到(无论exp或者expdp)
遇到ORA-01555,如果这个表有lob字段,就应该有有一定警觉
1、在导lob字段时,因为无法并行,导出会很慢。
2、lob字段使用的undo是local undo,是使用一定百分比的lob段空间作为undo使用。默认pctversion 10,即10%,可以字段级动态修改。
alter table tab modify lob(col_lob) (pctversion 20);
1、2都是导出慢属于正常场景,如果要排除3这种错误的情况,可以将lob字段表空间置为只读,或者使用受限模式启动来做导出。
3、lob字段有损坏行的场景。这种情况下也会报错ORA-01555和ORA-22924。需要使用如下sql来查询,然后清理掉lob数据或导出时屏蔽处理。
创建一个记录用表
create table corrupt_lobs (corrupt_rowid rowid, err_num number);
知道表上的lob列
DESC <TABLE_NAME>
Name Null? Type
---------- --------- ------------
<COL1> NOT NULL NUMBER
<LOB_COLUMN> BLOB
运行plsql块
--表名那里可以写成tab partition(part1)这种形式,以分区规模去查,减少浪费。本质是逐行fetch,然后catch错误打印到记录表。
--如果表上有2个lob字段,则要逐个字段来遍历
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);
n number;
begin
for cursor_lob in (select rowid r, <LOB_COLUMN> from <TABLE_NAME>) loop
begin
n:=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;
/
处理方法1-将有问题的lob行置为空
SQL> update <TABLE_NAME> set <LOB_COLUMN> = empty_blob()
where rowid in (select corrupt_rowid from corrupt_lobs);
( for BLOB and BFILE columns use EMPTY_BLOB; for CLOB and NCLOB columns use EMPTY_CLOB )
处理方法2-导出时直接屏蔽掉该行数据
% expdp system/<PASSWORD> DIRECTORY=my_dir DUMPFILE=<dump_name>.dmp LOGFILE=<logfile_name>.log TABLES=<SCHEMA_NAME>.<TABLE_NAME> QUERY=\"WHERE rowid NOT IN \(\'<corrupt_rowid>\'\)\"
参考778004.1
学习原理,积累工具。孵化思路,下笔有道。