Berkant KARDUMAN

Teknoloji günlüğü

LOB Alanlarda ORA-01555

LOB Bozulması

Export Sırasında Aşağıdaki hatayı gördük.


ORA-31693: "USER"."TABLE1" tablo veri nesnesi, yükleme/yüklemeyi kaldırma sırasında başarısız oldu ve hata nedeni ile atlanıyor.
ORA-02354: veriler içe/dışa aktarılırken hata oluştu
ORA-01555: kesit alma çok eski: 6 numaralı geri alma segmenti (adı "_SYSSMU6_2443381498$") çok küçük

Göründüğü gibi hata mesajı çok açıklayıcı :) Durum BLOB içeren tablodaki bazı verilerin bozulmasından kaynaklanıyor. Çözüm ise tek tek tüm kayıtları dolaşıp hatalı olanları tespit etmek. Bu script o iş için verilmiş.
drop table bad_rows;
create table bad_rows (row_id ROWID
                      ,oracle_error_code number);

set concat off
set serveroutput on
declare
  n number;
  error_code number;
  bad_rows number := 0;
  ora600 EXCEPTION;
  PRAGMA EXCEPTION_INIT(ora600, -600);
begin
   for cursor_lob in (select rowid rid, &&lob_column from
&&table_owner.&table_with_lob) loop
   begin
     n:=dbms_lob.instr(cursor_lob.&&lob_column,hextoraw('889911')) ;
   exception
    when ora600 then
     bad_rows := bad_rows + 1;
     insert into bad_rows values(cursor_lob.rid,600);
     commit;
    when others then
     error_code:=SQLCODE;
     bad_rows := bad_rows + 1;
     insert into bad_rows values(cursor_lob.rid,error_code);
     commit;  
   end;
  end loop;
  dbms_output.put_line('Total Rows identified with errors in LOB column:'||bad_rows);
end;
Burda BAD_ROWS isminde bir tablo oluşturuluyor ve tarama sonuçları bu tabloya yazılıyor. İşlem tablonun boyutuna göre biraz uzun sürebilir ancak bittiğinde elinizde bozulmuş olan tüm LOB lar için ROWID değerleri oluyor. Artık istenirse değerler NULL yapılabilir veya satır tamamı ile silinebilir.
-- silmeden önce kontrol etseniz iyi olur
delete from USER.TABLE1 t where exists (select * from bad_rows br where br.row_id=t.rowid)

Daha detaylı bilgi için Doc ID 846079.1 MOS dökümanına bakabilirsiniz.