【先声明,未经本人允许禁止转载抄袭】
周日早上接到通知,数据库出现故障。
看了一眼报错,ORA-00600 是Oracle内部错误,造成这个报错的可能性还是有很多的。
检查数据库状态、数据文件状态等信息,皆是正常的。
通过业务人员反馈,得知是因为通过plsql执行了 update clob字段操作,随后又进行回滚数据导致的。查了MOS,是一个Oracle BUG。
有三个解决思路:1、导出报错的表的数据,然后再重新导入;2、通过MOVE方式移动LOB段; 3、通过打补丁的方式。
只有一张表受了影响,共计35万条数据。我个人首选是方式2,然后再方式1。
首先尝试通过MOVE方式移动LOB段,创建了一个表空间,然后move table 到新的tablespace。首选这种方法呢也是因为这种表空间之间的数据迁移,效率还是比较高的 ,顺利的话这重量级的表可能10分钟就能够完成。 但在执行过程中报错ORA-01555。这也是一个非常高频率出现的报错信息,通常是因为受到undo影响,查看undo_retention参数是1440,这时候觉得应该并不是单纯的快照过旧的问题,检查undo发现了146个offline状态的回滚段,果然如此。
这个时候尝试导出数据,导出数据过程中也一样报了ORA01555错误,很明显CLOB数据块有损坏了,需要找到存在问题的数据,先清空掉才是,无论方法一还是方法二,都需要先清理这些数据才行。
通过以下方法排查问题数据,最终得到了4条数据,再通过EMPTY_CLOB()函数存在问题的CLOB字段。
declare
error_1555 exception;
pragma exception_init(error_1555,-1555);
n number;
begin
for cursor_lob in (select rowid r,xxxx from table) loop
begin
n := dbms_lob.instr (cursor_lob.xxxx , hextoraw ('AA')) ;
exception
when error_1555 then
insert into logtable values (cursor_lob.r, 1555);
commit;
end;
end loop;
end;
然后再执行方法一或者方法就都可以了,问题解决了。
行之所向,莫问远方