一次BTREE索引遇到ORA-08102錯誤的處理

還不算暈發表於2015-12-09

近期遇到一次ORA-08102錯誤,ORA-08102錯誤也屬於壞塊的範圍了,對此問題的分析處理及涉及的MOS官方文件記錄一下,供查閱參考。

1,首先是收到報錯時的alert日誌及TRACE檔案

alert日誌:
Mon Dec 07 13:24:30 2015
Errors in file /app/oracle/diag/rdbms/p1AAAAAdb/P1AAAAADB1/trace/P1AAAAADB1_j003_1519.trc:
ORA-00308: 無法開啟歸檔日誌 '/arc2_AAAAAdb/2_65597_790336456.arc'
ORA-27037: 無法獲得檔案狀態
HPUX-ia64 Error: 2: No such file or directory
Additional information: 3
Errors in file /app/oracle/diag/rdbms/p1AAAAAdb/P1AAAAADB1/trace/P1AAAAADB1_j003_1519.trc:
ORA-12012: 自動執行作業 "EDALDR"."LOAD_AAAAA_DCDATA_GLASS_ARRAY" 出錯
ORA-08102: 未找到索引關鍵字, 物件號 114615, 檔案 720, 塊 177653 (2)
ORA-06512: 在 "EDALDR.ARRAY_UTIL", line 375
ORA-06512: 在 "EDALDR.ARRAY_FILE_LOADER", line 65
ORA-06512: 在 "EDALDR.ARRAY_FILE_LOADER", line 651
ORA-06512: 在 "EDALDR.ARRAY_FILE_LOADER", line 1490
ORA-06512: 在 "EDALDR.AAAAA_DCDATA_GLASS_LOADER", line 385
ORA-06512: 在 "EDALDR.AAAAA_DCDATA_GLASS_LOADER", line 424
ORA-06512: 在 line 5


TRACE檔案:
*** 2015-12-07 13:14:45.753
*** SESSION ID:(1546.34091) 2015-12-07 13:14:45.753
*** CLIENT ID:() 2015-12-07 13:14:45.753
*** SERVICE NAME:(SYS$USERS) 2015-12-07 13:14:45.753
*** MODULE NAME:(DBMS_SCHEDULER) 2015-12-07 13:14:45.753
*** ACTION NAME:(LOAD_AAAAA_DCDATA_GLASS_ARRAY) 2015-12-07 13:14:45.753
 
oer 8102.2 - obj# 114615, rdba: 0xb402b5f5(afn 720, blk# 177653)
kdk key 8102.2:
  ncol: 2, len: 17
  key: (17):  07 78 73 0c 06 18 30 06 08 58 35 42 50 57 30 38 50
  mask: (4096): 

######################################

2.故障分析

從ALERT日誌的報錯:
ORA-08102: 未找到索引關鍵字, 物件號 114615, 檔案 720, 塊 177653 (2)
及TRACE檔案的內容:
oer 8102.2 - obj# 114615, rdba: 0xb402b5f5(afn 720, blk# 177653)
可以確認是出現了表和索引不一致;
MOS文件:Master Note for Handling Oracle Database Corruption Issues (文件 ID 1088018.1)
對此ORA-08102錯誤的定義:
An ORA-08102 indicates that there is a mismatch between the key(s) stored in the index and the values stored in the table. What typically happens is the index is built and at some future time, some type of corruption occurs, either in the table or index, to cause the mismatch.
對於此不一致涉及的索引和表的資料差異,可以使用如下語句排查:
查出8102對應的索引及表:
 select owner,object_name,object_type from dba_objects where object_id=114615;
 
 查詢索引型別:
 select index_name, index_type, table_name, PCT_THRESHOLD, CLUSTERING_FACTOR,status from DBA_indexes where table_name='ARRAY_CMN_GLASS_T';
  查索引對應的表及列
 set linesize 160
set pagesize 100
col owner for a15
col COLUMN_NAME for a20
select  a.OWNER,a.INDEX_NAME,a.table_name,b.column_name,b.column_length from dba_indexes a,dba_IND_COLUMNS b
 where a.index_name=b.index_name and a.owner='BYS' and  a.TABLE_NAME in(upper('T1'));
 查詢對應的段大小:
 select bytes/1024/1024 from dba_segments where segment_name='ARRAY_CMN_GLASS_T_I1';
索引和表的資料差異
Example:
Table name = DEPT, Index name = I_DEPT1, Indexed columns in index I_DEPT1 are: DEPTNO, DNAME.
SELECT /*+ FULL(t1) */ deptno, dname
FROM dept t1
MINUS
SELECT /*+ index(t I_DEPT1) */ deptno, dname
FROM dept t;
Make sure that the execution plan for the query uses the affected index; e.g. Index I_DEPT1 is shown in the execution plan.
######################################

3.對此8102錯誤成因的分析

參考:OERR: ORA-8102 "index key not found, obj# %s, file %s, block %s (%s)" (文件 ID 8102.1)
主要有三種:
1.Oracle bug.

2.Block corruption in the index or in the table. -->
確認到底哪種壞塊的方式:
Detect a corruption in the index:
ANALYZE INDEX <index name> VALIDATE STRUCTURE;
Detect a corruption in the table:
ANALYZE TABLE <table name> VALIDATE STRUCTURE;

3.Hardware / IO.
4.Function-based indexes (FBI)
######################################

4.問題解決:

在OERR: ORA-8102 "index key not found, obj# %s, file %s, block %s (%s)" (文件 ID 8102.1)文件中,給出的解決方法是重建索引,語句為:
alter index &index_name rebuild;
If the error is produced by a LOB INDEX, moving the LOB recreates the LOB INDEX:
alter table &table_owner.&table_with_lob
move LOB (&&lob_column) store as (tablespace &tablespace_name);
但是事實上,alter index &index_name rebuild;語句是不適合的;
這一點在文件:處理 Oracle7/8/8i/9i/10g/11g 中的 Oracle 塊損壞 (文件 ID 1526911.1)的(5B) 重建索引部分得到證實:
-------------
q.不要使用“ALTER INDEX ..  REBUILD”命令重建損壞的非分割槽索引,這一點非常重要,因為此操作通常會嘗試從包含壞塊的現有索引段中構建新索引。
"ALTER INDEX ... REBUILD ONLINE" and "ALTER INDEX ... REBUILD PARTITION ..."
不會從舊索引段中構建新索引,因此可以使用。
b.如果新索引包含的列為現有索引的子集,則 Create INDEX 可以使用現有索引中的資料。因此,如果您有兩個損壞的索引,應在重建之前將兩個都刪除。
--對rebuild動作而言,使用Index Fast Full Scan執行計劃,在讀取索引的過程中,以索引的葉子節點資料作為資料依據。如果rebuild的索引和資料表已經存在不一致的情況,那麼新生成的索引也一定是不一致的。
--rebuild online使用Table Access Full執行計劃,是基於對原始資料表的資料收集,而且是針對資料表進行的全表掃描操作。

本次故障,涉及的索引是普通的B*TREE索引,索引大小僅400M,最終是使用DROP索引後再建立的方式解決的。
(事實上本次遇到索引碎片很嚴重,重建後僅幾十M,對系統效能也是有提升的。
最初使用的是線上重建方式但是遲遲無法完成且在中斷後遇到online_index_clean無法完成等問題導致索引無法再次重建等問題,最終是通過dbms_repair.online_index_clean儲存過程不斷loop執行兩個小時得到清理,因此在"ALTER INDEX ... REBUILD ONLINE" 時也要注意在系統空閒時進行;大的索引最好停止相關業務後進行)

相關文章