資料泵expdp匯出遇到ORA-01555和ORA-22924問題的分析和處理

neverinit發表於2018-09-23

使用資料泵匯出資料庫資料時,發現如下錯誤提示:

ORA-31693: Table data object "CAMS_CORE"."BP_EXCEPTION_LOG" 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


1.檢視錶空間使用率

SELECT UPPER(F.TABLESPACE_NAME) AS "表空間名",
  D.TOT_GROOTTE_MB AS "表空間大小(M)",
  D.TOT_GROOTTE_MB-F.TOTAL_BYTES AS "已使用空間(M)",
  TO_CHAR(ROUND((D.TOT_GROOTTE_MB - F.TOTAL_BYTES) / D.TOT_GROOTTE_MB * 100,2),'990.99') || '%' "使用比",
  F.TOTAL_BYTES AS "空閒空間(M)",
  F.MAX_BYTES AS "最大塊(M)"
  FROM (SELECT TABLESPACE_NAME,
  ROUND(SUM(BYTES) / (1024 * 1024), 2) TOTAL_BYTES,
  ROUND(MAX(BYTES) / (1024 * 1024), 2) MAX_BYTES
  FROM SYS.DBA_FREE_SPACE
  GROUP BY TABLESPACE_NAME) F,
  (SELECT DD.TABLESPACE_NAME,
   ROUND(SUM(DD.BYTES) / (1024 * 1024), 2) TOT_GROOTTE_MB
  FROM SYS.DBA_DATA_FILES DD
  GROUP BY DD.TABLESPACE_NAME) D
  WHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME
ORDER BY 1;

2.看到ORA-01555錯誤,還以為是經典錯誤,嘗試調整undo_retention引數

SYS@cams>alter system set undo_retention=30000 scope=both;

修改後再次匯出,問題依舊存在,顯然問題和 undo_retention沒關係,再把引數改回去。


3.猜測是表空間有問題,這裡嘗試對 CAMS_CORE下的索引和LOB 進行表空間遷移。

(1)新建新的表空間

(2)拼接表空間遷移語句,前面已有文章寫到了表空間遷移方案

(3)執行表空間遷移語句

alter table CAMS_CORE.BP_EXCEPTION_LOG move lob(EX_STACK) store as (tablespace cams_core_lob);

執行到該語句的時候提示錯誤:

ORA-01555: 快照過舊: 回退段號  (名稱為 "") 過小
ORA-22924: 快照太舊

這裡,問題應該比較明顯了,有部分 LOB資料有問題。


4.尋找問題解決方案(MOS)

使用關鍵字 “expdp ORA-01555 ORA-22924  LOB”進行查詢:

Export Fails With Errors ORA-2354 ORA-1555 ORA-22924 And How To Confirm LOB Segment Corruption Using Export Utility (文件 ID 833635.1)


5.參考MOS給出的解決方案,動手處理問題

set concat off
 
create table corrupted_lob_data (corrupted_rowid rowid); 
set concat off
declare  
  error_1555 exception;  
  pragma exception_init(error_1555,-1555);  
  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_1555 then  
        insert into corrupted_lob_data values (cursor_lob.r);  
        commit;  
    end;  
  end loop;  
end;  
/  
 
Enter value for table_owner: EX_STACK
Enter value for table_owner: CAMS_CORE
Enter value for table_with_lob: BP_EXCEPTION_LOG
old   6:   for cursor_lob in (select rowid r, &&lob_column from &table_owner.&table_with_lob) loop
new   6:   for cursor_lob in (select rowid r, EX_STACK from CAMS_CORE.BP_EXCEPTION_LOG) loop
old   8:       num := dbms_lob.instr (cursor_lob.&&lob_column, hextoraw ('889911')) ;
new   8:       num := dbms_lob.instr (cursor_lob.EX_STACK, hextoraw ('889911')) ;
 
PL/SQL procedure successfully completed.


檢視存在問題的資料記錄:

select * from CAMS_CORE.BP_EXCEPTION_LOG
where rowid in ( select * from CAMS_CORE.corrupted_lob_data );

確實存在 3條資料, CLOB 欄位資料大小為 ,顯然有問題。

MOS上給出的匯出方案是將問題資料exclude掉,這裡為了徹底解決問題,將3條資料匯出為csv檔案,然後刪除。然後再次匯出資料庫資料,不再提示報錯。

 

6.結合應用分析問題的由來。

根據有問題的資料,讓開發人員去檢查應用日誌。檢查時發現對應時間點的應用日誌有殘缺,不能繼續往下分析。同時,根據問題發生的時間點,瞭解到當時工程師在給伺服器做遷移,結果伺服器強制重啟(應用和資料庫一起),導致了部分資料損壞。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31394774/viewspace-2214736/,如需轉載,請註明出處,否則將追究法律責任。

相關文章