- 那是在2021年7月30日的下午,在整理公司服务器中备份文件时发现的问题
- 当时发现备份的数据虽然有文件,但是日志中存在报错,并且备份出来的文件无法进行还原
- 因为没遇到过这个问题,但是也是查了很多资料,最后在2021年7月31日凌晨处理掉了这个问题
- 当时还发了个朋友圈进行记录,之前带过我的哥跟我说,他从业10年了,处理过各种oracle问题,这个问题居然也没遇到过
- 先看日志中的报错信息
ORA-01555: snapshot too old: rollback segment number with name "" too small ORA-22924: snapshot too old
- 在排查过程中发现可能是由于LOB字段数据损坏造成的
- 解决LOB字段的ORA-01555错误的第一步是检查是否有数据损坏
- 创建一个虚拟表,用于存储损坏LOB的所有rowid
SQL>create table corrupt_lobs (corrupt_rowid rowid, err_num number);
- 查找包含LOB数据的列名
SQL> DESC bd_psndoc Name Null? Type ---------- --------- ------------ NAME NOT NULL varchar2 PHOTO BLOB
- 执行以下PL/SQL块以识别损坏的行。确保用相应的lob列和表名替换<lob Column>和<Table name>。
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, photo from nc633.bd_psndoc) loop begin num := dbms_lob.instr (cursor_lob.photo, 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; /
- 执行上述过程后,表“corrupt_lobs”将包含损坏行的rowid,查看损坏数据的rowid
- 如果您在同一个表中有多个LOB列,或者希望检查多个表,请再次执行上述步骤
SQL>select * from corrupt_lobs;
- 发现确实有坏的数据,为了验证导出报错问题是不是该数据引起的,单独备份这张表,去掉3条有问题的数据
- 结果当然是成功了,确认了就是这3条数据的LOB段损坏造成的
expdp ******/******* directory=db_bak dumpfile=test.dmp logfile=test.log tables=bd_psndoc query=\"where rowid not in \'aaewbsaagaacewaac\',\'aaewbsaagaacewaaf\',\'aaewbsaagaacewaag\'\"
- 一旦确定了损坏,需要消除损坏的数据,以解决ORA-1555错误
- 第一种:使用物理备份恢复LOB段
- 第二种:使用UPDATE语句清空受影响的LOB(由于该字段储存的是用户的照片,所以楼主采用该方式清空了对应行的照片)
update nc633.bd_psndoc set photo = empty_blob() where rowid in (select corrupted_rowid from corrupt_lobs); commit;
- 然后再次进行数据全量备份就没有问题了
- 最后问题解决了,但是这3条数据为什么会损坏,楼主也不知道具体原因
- 由于种种原因吧,也没有深入研究