數據泵expdp導出遇到ORA-01555和ORA-22924問題的解決


使用數據泵導出數據庫數據時,發現如下錯誤提示:

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

個人認為報快照過舊絕大部分可能原因是undo表空間不足或保留時間設置問題。本次着重討論表數據損毀引起的報錯。

 

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參數 

alter system set undo_retention=10800 scope=both;

show parameter undo_tablespace

 

 必要時需要更換undo表空間 步驟如下

 

select tablespace_name, file_id, file_name,round (bytes / (1024 * 1024), 0) total_space from dba_data_files where tablespace_name='UNDOTBS1';

 創建undo表空間

SQL>  create undo tablespace UNDOTBS2 datafile '/u01/app/oracle/oradata/orcl/undotbs02.dbf' size 20000M;
Tablespace created.

 

更換默認undo表空間

SQL> alter system set undo_tablespace = undotbs2 scope=both;
System altered.

 

查看配置是否生效 

SQL> select tablespace_name , status , count(*) from dba_rollback_segs group by tablespace_name , status;
TABLESPACE_NAME                STATUS             COUNT(*)
------------------------------ ---------------- ----------
UNDOTBS1                       OFFLINE                  10
SYSTEM                         ONLINE                    1
UNDOTBS2                       ONLINE                   10

 

檢查確認UNDOTBS1中沒有ONLINE的segment
SQL> select status,segment_name from dba_rollback_segs where status not in ('OFFLINE') and tablespace_name='UNDOTBS1';
no rows selected

 

刪除舊的UNDOTBS1
SQL> Drop tablespace UNDOTBS1 including contents and datafiles;
Tablespace dropped.

 

 

猜測是表空間有問題,這里嘗試對 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數據有問題。

 

尋找問題解決方案(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給出的解決方案,動手處理問題

 

1.創建表存放查詢出有問題的rowid

 

set concat off

  
create table corrupted_lob_data (corrupted_rowid rowid);   --存放損毀數據的rowid
set concat off
 
 
2.收集有問題字段中存在問題值的rowid
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;  
/  
 
 
--lob_column  表的字段名(一般掃描blob、clob字段)
--table_owner  表的所有者
--table_with_lob 表名 
  
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.
 
3.通過查詢出的rowid查看存在問題的數據記錄:
select from test.test1
where rowid in select from test.corrupted_lob_data );

 或

 

 

 

 

 

確實存在 3條數據, CLOB 字段數據大小為 ,顯然有問題。 

MOS上給出的導出方案是將問題數據exclude掉,這里為了徹底解決問題,將3條數據導出為csv文件,然后刪除。然后再次導出數據庫數據,不再提示報錯。

 

補充:或用如下方式過濾問題數據expdp備份 

expdp test/test123 parfile=his.par directory=DMPDIR

 

vim his.par

dumpfile = 208306.dmp
logfile = 208306.log
tables = test1,test2,test3 
query = (
test1:"where rowid not in ('AAAameAAHAAM5c6AAJ')",
test2:"where rowid not in ('AAAamhAAIAAHTa9AAG','AAAamhAAJAAHhSRAAF','AAAamhAAKAAL3g3AAD')",
test3:"where rowid not in ('AAAa3oAALAAMirTAAF','AAAa3oAAKAANm7/AAB')"
)

注:query中的特殊字符不在參數文件中,前面需要加轉義字符。

 

 4.或者可以對問題數據進行刪除或置空

 

update "WF_PROCESS_RUNNING"

 

     set PROCESS_XML = empty_clob()

 

     where rowid in (select corrupted_rowid from test123_PROCESS_XML); 

 

     commit;

注:清理前請先與業務部門確認影響,二進制數據一般是很難被修復的。

 

 

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM