我们在online rebuild 或者create index online过程中,服务器进程会将字典表ind#的flag标志位在原来数字的基础上增加256或者512.
根据创建ind$表的语句注释可以知道,如果是索引新建(online),则增加256,如果是索引重建(online),则是512.上图中的0X100,0X200都是16进制,需要转化为10进制。
原则上online create/rebuild index的的清理工作由实际操作的服务进程负责完成,这种清理在DDL语句成功的情况下包括一系列数据字典的维护,在该DDL语句失败的情形中包括对临时段的清理和数据字典的维护,无论如何都需要drop在线日志中间表 SYS_JOURNAL_nnnnn(nnnn为该索引的obj#)。数据字典的维护工作就包含对IND$基表中相应索引记录的FLAGS标志位的恢复,但是如果服务进程在语句执行过程中意外终止的话,那么短时间内FLAGS标志位字段就无法得到恢复,这将导致对该索引的后续操作因ORA-8104错误而无法继续:
SMON负责在启动后(startup)的每小时执行一次对IND$基表中因在线创建/重建索引失败所留下记录的清理。
注意因为SMON进程的清理工作每小时才执行一次,而且在工作负载很高的情况下可能实际很久都不会得到清理,在这种情景中我们总是希望能尽快完成对索引的在线创建或重建,在10gr2以后的版本中我们可以直接使用dbms_repair.online_index_clean来手动清理online index rebuild的遗留问题:
online rebuild 创建前:
select flags from ind$ where obj#=115225;
FLAGS
----------
2050
这个2050 可以这么解释:
2050=2+2048=16进制的 2+800
查看ind$的创建语句会知道:
2050代表:2+800=表被分析过(/* analyzed : 0x02 */)+表是被dbms_stats分析的(/* global stats : 0x800 */)
表只有被dbms_stats分析过, global stats的状态才是yes.
online创建后:
select flags from ind$ where obj#=115225;
FLAGS
----------
2562
SELECT 2562-2050 FROM dual;
2562-2050
----------
512
增加的512可以这么解释:
select to_char(512,'xxxxxx') from dual;
TO_CHAR(512,'X
--------------
200
/* index is being online rebuilt : 0x200 */
索引正在被online重建
杀掉重建索引的会话:
kill -9 16522
alter index hades.NAQ_TRADE_ITEM_TRADENO_Ind rebuild online;
*
ERROR at line 1:
ORA-08104: this index object 115225 is being online built or rebuilt
DECLARE
RetVal BOOLEAN;
OBJECT_ID BINARY_INTEGER;
WAIT_FOR_LOCK BINARY_INTEGER;
BEGIN
OBJECT_ID := 115225;
WAIT_FOR_LOCK := NULL;
RetVal := SYS.DBMS_REPAIR.ONLINE_INDEX_CLEAN();
COMMIT;
END;
/
但是如果表上存在事务或是有TM锁,那么这个PL/SQL块会久久的HANG在那里。直到事务结束。