oracle如何清除创建失败的索引

在创建一张大表的索引时,因为没有加并行而导致创建时间很长,这时候如果终止操作,比如直接关闭终端,然后再次登录创建时就会报错ORA-00095提示对象名字已被用,而去删除对象时又报错ORA-08104索引正在被创建。

 

SQL> drop index xxx.BM_IX;

drop 
index 
xxx.BM_IX
                
*
ERROR 
at 
line 1:
ORA-08104: this 
index 
object 1443829 
is 
being online built 
or 
rebuilt
SQL> 
select 
object_id 
from 
dba_objects 
where 
object_name=
‘BM_IX‘
;
 
OBJECT_ID
----------
   
1443829
$ oerr ora 08104
08104, 00000, 
"this index object %s is being online built or rebuilt"
// *Cause:  the 
index 
is 
being created 
or 
rebuild 
or 
waited 
for 
recovering 
//          
from 
the online (re)build 
// *
Action
: wait the online 
index 
build 
or 
recovery 
to 
complete  

从oerr工具看到的ORA-08104的解释是索引并没有创建失败,而是在终端关闭之后,创建的操作还在继续进行。创建或者重建索引时,系统会创建一个临时日志表,这张表被用于存放创建或者重建索引期间产生的日志信息,同时在基表IND$中这个索引的FLAG字段上会被设置为BUILD或者REBUILD标识,当索引信息变更时会把变更信息存入日志表。如果索引创建或者重建失败,这个日志表和数据字典中的状态位都需要后台进程smon进行清理。

因此这里的索引不能被删除是因为后台进程smon还没来得及清理相应的临时段和标志位,认为online rebuild操作还在进行。

那么现在如何终止rebuild index这一操作?查找metalink得到一篇文档:ORA-600 [12813] When Dropping A Table Partition After a Failed IndexRebuild (文档 ID 803008.1)。它给出了两种方法:

1)使用包dbms_repair包来清理

如果在出现问题的对象的数据库活动能停下来,则直接简单地执行如下语句即可:

connect 

as 
sysdba
select 
dbms_repair.online_index_clean(<problem 
index 
object_id>) 
from 
dual; 

 

exit    

2)使用PL/SQL block调用dbms_repair包来清理

如果在出现问题的对象的数据库活动不能停下来,则如下的PL/SQL block来处理

 

注:加上dbms_repair.lock_wait表示不是立刻清理,需要不断的寻找资源锁,直到抢到为止

declare
  
isClean boolean;
begin
  
isClean := 
FALSE
;
  
while isClean=
FALSE 
loop
isClean := dbms_repair.online_index_clean(dbms_repair.all_index_id,
                                          
dbms_repair.lock_wait);
dbms_lock.sleep(2);
  
end 
loop;
  
exception 
when 
others 
then 
  
RAISE; 
end
;

 

/    

--原文:http://blog.itpub.net/28218939/viewspace-2638333/

1)使用包dbms_repair包来清理

如果在出现问题的对象的数据库活动能停下来,则直接简单地执行如下语句即可:

1 2 3 connect  as  sysdba select  dbms_repair.online_index_clean(<problem  index  object_id>)  from  dual;  exit

2)使用PL/SQL block调用dbms_repair包来清理

如果在出现问题的对象的数据库活动不能停下来,则如下的PL/SQL block来处理

注:加上dbms_repair.lock_wait表示不是立刻清理,需要不断的寻找资源锁,直到抢到为止

1 2 3 4 5 6 7 8 9 10 11 12 13 14 declare    isClean boolean; begin    isClean :=  FALSE ;    while isClean= FALSE  loop isClean := dbms_repair.online_index_clean(dbms_repair.all_index_id,                                            dbms_repair.lock_wait); dbms_lock.sleep(2);    end  loop;    exception  when  others  then     RAISE;  end ; /

相关文章