近期遇到一次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" 时也要注意在系统空闲时进行;大的索引最好停止相关业务后进行)