cancel掉正在online创建的索引带来的问题

上一篇 / 下一篇  2007-07-03 00:00:00 / 个人分类:管理

问题提出:
一个OLTP系统,运行在REDHAT AS4U3的ORACLE 10.2.0.2的双节点RAC上,其中一个表的数据量在1500万左右,需要在上面创建一个索引,于是采用了online的模式,创建到一半的时候,发现因为开了多个plsql developer导致所以创建错了,创建到了另外一个库的相同的表上了,于是赶紧点取消,问题由此引发。

1、发现的问题是前台业务人员反映某个更新操作不能使用,然后查找被阻塞的session所执行的sql,发现这些session都是执行一个相同的会话,都在更新正在创建索引的那个字段。这时怀疑到是否是因为创建索引的时候未使用online关键字,虽然点了取消,但是oracle的进程还在运行中,导致这个字段被锁住。由于session数目急剧增加,于是先kill掉了一批对这个表的这个字段进行update的被阻塞的会话。
2、核对之前创建索引的sql,确认使用的是online的模式。于是到v$sql里面查找,想找到正在运行的创建索引的那个会话,然后找到这个会话对应的操作系统的PID,然后直接到操作系统中kill掉。但是在v$sql视图中没有发现创建索引的语句。
3、查找user_objects视图,发现创建的索引已经在视图中存在,于是想到直接去drop掉这个索引。但是drop索引的时候发生ORA-08104 (this index object xxxxx is being online built or rebuilt) 错误,rebuild时也会发生相应的错误。
4、这时注意到数据库后台很多ora-600的报警,ORA-00600: internal error code, arguments: [kdiblUnpackEntry:startRowidAlign], [67346168], [125], [], [], [], [], [],于是上metalink搜索,没有发现有用的信息。后来所有ORA-08104,在fenng的blog上发现了相关的文章,说如果一个online创建的索引被中途cancel或者kill掉,则该过程失败之前创建的一些临时对象由 SMON 负责清除,糟糕的是, SMON 可能会不作为,因为online rebuild或create失败后,oracle会做以下两件事情:
1.smon进程清除ind$基表,将相应的索引的flags更改为0.这步操作每隔一小时做一次。
2.smon进程清理临时段。每隔两小时做一次,而且不知道它多久才能干完。
而在 10g 版本, Oracle 的 DBMS_REPARE 包新增了: online_index_clean ,能够手工做SMON干的活:
dbms_repair.online_index_clean(
object_id IN BINARY_INTEGER DEFAULT ALL_INDEX_ID,
wait_for_lock IN BINARY_INTEGER DEFAULT LOCK_WAIT)
RETURN BOOLEAN;
查找oracle的手册,找到这个包的用法,开始执行。
4、经过漫长的等待,终于执行完毕,但查找user_objects发现这个索引还在,而且数据库后台还在不停的报ORA-600错误出来。
5、因为是线上系统,经不起重启和等待,于是决定冒险,进行手工清除。首先查找到在建索引的object_id,然后执行update ind$ set flags=0 where obj#=object_id,然后开始删除索引,还是ORA-08104,rebuild也是ORA-08104。查看ind$中的索引flag信息,居然又蹦回来了。来回折腾几次,当中包括把标志更新成0后再运行dbms_repair.online_index_clean包,都不解决问题。于是开始直接删除SYS_JOURNAL_nnnn,其中的nnnn为索引的object_id。而且要先update flag字段再删除此表,如果先删除SYS_JOURNAL_nnnnn临时表格,然后再将index的flags状态改为0的话,则会报出ora-600 [4610]号错误,也就是数据字典不一致的错误。
6、按照上面说的干完后,发现问题依旧,但是600的错误发生了改变,ORA-00600: internal error code, arguments: [25027], [6], [1], [], [], [], [], [],再次查找metalink,没有发现。这时发生了更严重的问题,对这个表的insert也不能执行,业务影响范围被扩大了!
7、按照上面的方法,重新把ind$中的flag字段更新为0,然后关闭一个节点,问题依旧,打开节点,关闭另一个节点,问题依旧,然后把节点重新打开。
8、开始采取紧急方案,准备宕机维护,首先把此表的数据CTAS为另一个表,然后把新的备份表的索引都建好,表分析做好,准备停前台业务,把问题表rename为备份表,备份表rename为正式表。此方案成功。
9、问题远没有结束,表切换完成后,开始drop问题表,不成功,drop问题索引,也不成功,于是把它放在那里不管它了。第二天,发现数据库错误发生。log如下:
ORA-00600: internal error code, arguments: [25027], [6], [0], [], [], [], [], []
ORA-06512: at "SYS.DBMS_STATS", line 13313
ORA-06512: at "SYS.DBMS_STATS", line 13620
ORA-06512: at "SYS.DBMS_STATS", line 13737
ORA-06512: at "SYS.DBMS_STATS", line 13696
ORA-06512: at line 1
因为之前系统设置的是对整个sechema进行每天分析的,现在对这个表的分析也有问题,于是把分析整个schema停掉,改成只分析几个数据变化比较大的表。
10、隐患依旧,不知道问题什么时候爆发,于是想到拿RMAN备份恢复一个库出来,看看这些错误的信息是否被写入了REDO LOG,恢复出来的库是否存在相同的问题,哪天万一宕了,最坏可以来一个全库恢复。不幸的是恢复出来的库也存在同样的问题。
11、在恢复库中测试,干脆把ind$中相应的记录备份一下,然后直接把记录删除,然后表可以drop掉了。但是查看user_object视图,发现索引还在,只不过被放在了垃圾箱,把ind$的记录再导回来,进行purge操作,失败,错误相同。

附录:ind$表中的flag字段说明:
0x01 : unusable (dls)
0x02 : analyzed
0x04 : no logging
0x08 : index is currently being built
0x10 : index creation was incomplete
0x20 : key compression enabled
0x40 : user-specified stats
0x80 : secondary index on IOT
0x100 : index is being online built
0x200 : index is being online rebuilt
0x400 : index is disabled
0x800 : global stats
0x1000 : fake index(internal)
0x2000 : index on UROWID column(s)
0x4000 : index with large key
0x8000 : move partitioned rows in base table
0x10000 : index usage monitoring enabled

总结:首先在维护OLTP系统的时候要小心仔细,尤其是比较大的操作,最好再一个数据量相当的库上测试下执行时间,大的更新删除等操作还要监控回滚空间是否足够。另外,不知道plsql developer能否实现连接不同的数据库的时候显示不同的颜色,或者给个啥提示,如果不行,那最好所有的命令都到终端去执行,比如SecureCRT,可以为不同的机器设置不同的颜色,提醒现在是否在生产库。
问题依旧,只求菩萨保佑!



TAG:

oradbHome 引用 删除 oradbHome   /   2008-05-27 13:13:47
我是在9i 越到到此问题.重启也没有作用.也会司ctas 解决的.
 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

日历

« 2008-10-11  
   1234
567891011
12131415161718
19202122232425
262728293031 

我的存档

数据统计

  • 访问量: 1600
  • 日志数: 250
  • 建立时间: 2008-01-01
  • 更新时间: 2008-01-01

RSS订阅

Open Toolbar