索引块丢失导致的ora-08102错误及解决方案

索引块丢失导致的ora-08102异常及解决方案

       “出现Ora-8102的原因一般是由于索引中的KEY和TABLE里的相关字段值不同导致数据不一致引起。一般来说,出现ORA-8102,是由于数据库逻辑或者物理故障引起的,损坏的可能是表数据,也可能是索引数据。如果损坏的是索引数据,那么只需要将索引重建就可以使表和索引数据一致,从而解决问题。如果损坏的是表数据,那么要看损坏的范围,如果只是损坏了某一行,那么纠正某一行的数据就可以了,如果损坏的面积较大,那么处理起来就比较复杂。”

        目前开发的一个系统,每天需要大量的删除和插入操作,最近遇到了异常,当删除数据时报错,类似:

 ora-08102:index key not found,是索引出了问题,重建索引即可。使用以下语句重建:

alter index indexname rebuild (online);

 网上找了下,整理了需要重建索引的场景和标准:

 

1、考虑重建索引的场合

  • 表上频繁发生update,delete操作(我们目前的系统会频繁的delete和insert)
  • 表上发生了alter table ..move操作(move操作导致了rowid变化)

 2、重建标准

    索引重建是否有必要,一般看索引是否倾斜的严重或者是否浪费了空间:Oracle使用B树构建索引,如果B数的高度超过3 或者删除的索引占用的空间超过了20%,即表明需要重建(以上信息可以通过视图INDEX_STATS获得)。有两种方式可以使用:

   1) drop 原来的索引,然后再创建索引;
    2) alter index indexname rebuild (online);
    方式一:无法在24*7环境中实现。
    方式二:可以在24*7环境中实现,我们目前使用这种方式。

 

下面是我整理的一个sql脚本,可以定时调用执行,防止ora-08102异常,将indexname替换为具体的索引名称即可:

declare
  type IdxInfo is record
  (
    height number,
    delPer number
  );
  info IdxInfo;
begin
  execute immediate 'analyze index indexname validate structure';
  select height, t.del_lf_rows/t.lf_rows  into info from index_stats t where name = 'indexname';
  dbms_output.put_line('per:'||info.delPer||' h:'||info.height);
  
  if info.height >=4 or info.delPer > 0.2 then
    dbms_output.put_line('need rebuild');
    execute immediate 'alter index indexname rebuild online';
  else
    dbms_output.put_line('no need rebuild'); 
  end if;
exception
  when others then
    execute immediate 'alter index indexname rebuild online';
    dbms_output.put_line('error'|| sqlerrm);
end;

 

 

参考:ORACLE INDEX重建       视图INDEX_STATS描述