среда, 5 августа 2009 г.

ORA-01555: snapshot too old: rollback segment number with name "" too small

В процессе выполнения экспорта схемы со следующей командой выдало ошибку EXP-00056: ORACLE error 1555 encountered
ORA-01555: snapshot too old: rollback segment number with name "" too small
ORA-22924: snapshot too old
-----------------------------------------------------------------------------------------
mknod $PIPE p
(gzip < $PIPE > $BACKUP_FILE.dmp.gz) &

exp \
userid=system/fuckoracle \
owner=NAT_ADMIN \
consistent=Y \
direct=Y \
file=$PIPE log=$BACKUP_FILE.log
------------------------------------------------------------------------------------------
В данном случае, увеличение значения UNDO_RETENTION и размера UNDOTBS не исправило дело.
По этому поводу в металинке нашла ноту Doc ID: 833635.1


All the above errors are produced when exporting, because the LOBs stored in the table to be exported might be corrupted.
To have this checked a PLSQL block should be run against the table.



Вот решение которое предлагается:

1. Create a new temporary table for storing all rowids of the corrupted LOBs. Let's call it "corrupt_lobs"

SQL> create table corrupt_lobs (corrupt_rowid rowid);

2. Make a desc on the table containing the LOB column:

DESC LOBDATA

Name Null? Type
----------------------------------------- --------
ID NOT NULL NUMBER
DOCUMENT BLOB


Вставить название таблицы и название колонки содержащее LOB объект в процедуру вместо LOBDATA и document соответственно



Run the following PLSQL block
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, document from LOBDATA ) loop
begin
n:=dbms_lob.instr(cursor_lob.document,hextoraw('889911'));
exception
when error_1578 then
insert into corrupt_lobs values (cursor_lob.r);
commit;
when error_1555 then
insert into corrupt_lobs values (cursor_lob.r);
commit;
when error_22922 then
insert into corrupt_lobs values (cursor_lob.r);
commit;
end;
end loop;
end;
/

In the end all rowids of the corrupted LOBs will be inserted into the corrupt_lobs newly created table.

A possible solution would then be to empty the affected LOBs using:
Eg:
SQL> update LOBDATA set document = empty_blob()
where rowid in (select corrupt_lobs from corrupt_lobs);



Для дальнейшего подтверждения повреждения, попробуйте запустить экспорт на эти сегменты

% exp scott/tiger file=test2.dmp log=test2.log tables=EMP query=\"where rowid=\' AAEWBsAAGAAACewAAG \' \"


В случае если данный процесс выдаст ошибку,можно считать повреждение подтвержденным.
Металинк предлает одно из следующих решений для данной проблемы:

-- Restore and Recover the LOB segment using physical backup.

Or
-- Empty the affected LOBs using UPDATE statement as mentioned in the Note 787004.1

SQL> update EMP set EMP_XML = empty_blob()
where rowid in (select Corrupted_rowid from corrupted_lobs);

Or
-- Perform the export excluding the corrupted rowids.

Using datapump export:

% expdp scott/tiger directory=data_pump_dir dumpfile=test.dmp logfile=test.log tables=EMP query=\"where rowid not in \(\'AAEWBsAAGAAACewAAC\',\'AAEWBsAAGAAACewAAF\' ,\'AAEWBsAAGAAACewAAG\'\)\"

Using normal export:

% exp scott/tiger file=test.dmp log=test.log tables=EMP query=\"where rowid not in \(\'AAEWBsAAGAAACewAAC\',\'AAEWBsAAGAAACewAAF\' ,\'AAEWBsAAGAAACewAAG\'\)\"