01555 и BLOB

Задача: полный экспорт БД.

Ну вот те раз!
"Job "SYSTEM"."SYS_EXPORT_FULL_01" completed with 1 error(s)
at Fri Nov 3 00:20:04 2017 elapsed 0 00:30:22"

Ar-r-r-r-r!!!

ORA-31693: Table data object "ARDOME"."XFER_HISTORY" failed to load/unload and is being skipped due to error:
ORA-02354: error in exporting/importing data
ORA-01555: snapshot too old: rollback segment number with name "" too small
ORA-22924: snapshot too old

Странно, не указана ссылка на табличное пространство UNDO, столкнулся с этим первый раз. Прошёлся по стандартной схеме:
0) Увеличение объёма UNDO и длительности UNDO_RETENTION

ORA-22924 — сигнализирует о проблемах с LOB

Вот что было предпринято, но не помогло:
1) alter table ARDOME.XFER_HISTORY modify lob (XFH_PAYLOAD) (pctversion 100);
2) alter table ARDOME.XFER_HISTORY modify lob(XFH_PAYLOAD) (retention);

Не помогло…

Есть вероятность того, что повреждены BLOB в этой таблице, для того, чтобы определить какие именно:

1) Создадим пустышку для хранения ROWID и кода ошибки ERR_NUM
SQL> create table corrupt_lobs (corrupt_rowid rowid, err_num number);

2) Найдём имя столбца который содержит LOB данные:
SQL> DESC ARDOME.XFER_HISTORY
———-
XFH_ID      NOT NULL NUMBER(10
XFH_PAYLOAD      BLOB
 

3) Выполним следующий блок:

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);
num number;
begin
for cursor_lob in (select rowid r, &&lob_column from &table_owner..&table_with_lob) loop
begin
num := 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;
/

Он у нас запросит и мы введём (имя столбца, имя владельца и имя таблицы):

Enter value for lob_column: XFH_PAYLOAD
Enter value for table_owner: ARDOME
Enter value for table_with_lob: XFER_HISTORY

4) После выполнения вышеописанной процедуры в созданной табличке мы можем найти (или не найти) ROWID повреждённых лоб:
select * from corrupted_lob_data;

У меня оказалось 3 строки:
corrupt_rowid     err_num
——————————-
AAAXd7AAKAAK5+oAAU    1555
AAAXd7AAKAAK5+oAAV    1555
AAAXd7AAKAAK5+oAAW   1555

В этой ситуации можно:
-восстановить эти LOB сегменты из физического бекапа;

-почистить (обнулить) повреждённые LOBы используя UPDATE:
update <owner>.<tablename>
set    <lob column> = empty_blob()
where  rowid in (select corrupted_rowid from   corrupted_lob_data);
commit;

В моей ситуации обошёлся тем, что выгрузил дамп БД без повреждённых строк:
expdp \"/as sysdba\" parfile=export_options.par

Содержимое export_options.par:
directory=DUMP_EXP
dumpfile=mamdb01_full.dmp
logfile=mamdb01_full.exp.log
full=y
query="where rowid not in ('AAAXd7AAKAAK5+oAAU', 'AAAXd7AAKAAK5+oAAV', 'AAAXd7AAKAAK5+oAAW')"