这个专题讲一些日常运维的异常处理
开发人员找说应用连接不上,报ORA-01555错误
第一反应当然是查询是否undo表空间不足
通过如下命令查询
SELECT round(((SELECT (NVL(SUM(bytes), 0))FROM dba_undo_extents
WHERE tablespace_name =
(select value from v$parameter
where lower(name) = 'undo_tablespace')
AND status IN ('ACTIVE', 'UNEXPIRED')) * 100) /
(SELECT SUM(bytes) FROM dba_data_files
WHERE tablespace_name =
(select value from v$parameter
where lower(name) = 'undo_tablespace')), 2) PCT_INUSE
FROM dual
使用率很低,而且数据库重启过,我们暂时排除
我们首先执行手动执行该语句,在sqlplus中运行也是报错
在plsql中执行显示value error
字段是clob字段,看来这就是原因了,是由于clob字段损坏导致
因为CLOB字段的undo信息是存储在clob块中的,其保留策略通过PCTVERSION(百分比) 和RETENTION(时间)字段控制
我们通过如下语句查询该clob字段是否有损坏
将<your_clob_column>替换成value error的字段名
将<your_table_with_clcob_column>替换成该字段所在的表名
set serverout on
exec dbms_output.enable(100000);
declare
page number;
len number;
c varchar2(10);
charpp number := 8132/2;
begin
for r in (select rowid rid, dbms_lob.getlength (<your_clob_column>) len
from <your_table_with_clcob_column>) loop
if r.len is not null then
for page in 0..r.len/charpp loop
begin
select dbms_lob.substr (<your_clob_column>, 1, 1+ (page * charpp))
into c
from <your_table_with_clcob_column>
where rowid = r.rid;
exception
when others then
dbms_output.put_line ('Error on rowid ' ||R.rid||' page '||page);
dbms_output.put_line (sqlerrm);
end;
end loop;
end if;
end loop;
end;
/
这时我们查出来有三行,我们记住其rowid
我们可以利用如下语句对该错误进行跟踪,当发生错误时alert日志会有记录并生成trace文件
alter system set events '1555 trace name errorstack level 3';
如果在导出的话,clob字段损坏会导致失败,这时我们可以使用如下参数跳过指定的行
expdp \"/ as sysdba\" tables="ISUGDP"."TEXT_FOR_ECP" directory=DROPZONE dumpfile=table.dmp logfile=table.log QUERY=\"WHERE rowid NOT IN \(SELECT CORRUPTED_ROWID FROM CORRUPTED_ROWS\)\"
知道了原因后,如果这几行数据很重要,则需要别的恢复手段将其恢复(RMAN)
如果不需要这几行数据我们可以将其删除
delete from table where rowid='AAAV1RAAEAAD5dGAAC';
之后问题解决
https://dbpilot.net/2018/02/05/ora-1555-snapshot-too-old-due-to-corrupted-lobs/