truncate异常中断后,发生DFS LOCK HANDLE

环境:
oracle 9206 三节点rac。hp 11.11。

【10月29日,故障发生】

在一次truncate一个大表的过程中(以下操作均在节点1(gdrac1)上操作):

我们执行了truncate table xxx reuse storage,希望通过分步回缩extent的方式在truncate该表。

但是在truncate table ALERTBUFF reuse storage的时候,网络中断了。再次登录db的时候,发现该session还在,找到其sid,serial#,spid,kill掉session和os中的process,希望重新跑。

检查起状态已经变成killed,但是其dba dml lock中仍然有其锁存在:

在alertlog中有告警信息:

相关的pmon trace file点击此处:gdrac1_pmon_7976

当时关于这个表的任何操作都无法进行!即使是select也会有library cache lock。

itpub上有好多热心的大侠帮忙想办法(点击此处查看),如去找pmon中的dead process,然后在os级把这个process杀掉。对该表做rename等等,但是结果都是该process我在操作当晚已经kill掉。

【10月30日,故障升级】

随着时间的推移,还发现了除了alertbuff表,其他的表也收到了影响:

desc Service_exclusive这个表长期无响应。

对这个表select 也是library cache lock:

同时在metalink中提交了SR,oracle说是一个bug(5732292),没有临时解决办法(no workaround),唯一的解决办法是重启数据库(You must try restarting the instances to see if this helps fix it.)

根据SR的建议,计划重启rac2和rac3,看是否能恢复;若不能,另找机会重启所有节点:

【11月1日,重启rac2,rac3】

一、计划:
停2个节点,留一个节点跑还不会造成业务中断(业务波动)。停3个节点的话就是业务全影响了(业务中断)。
尝试影响小的恢复,oracle在sr中也说停rac2,rac3,检查是否恢复。如果此时不能恢复,再shutdown abort rac1。因此从影响角度考虑,先重启2个节点,看是否能解决。如果不能,再安排重启3节点。

为减少对业务影响,尽量在不完全down数据库的情况下尝试恢复。在凌晨业务不忙的时候操作:
1.停部分非单点的应用,
2.停侦听,job process设置为0,kill LOCAL=NO,shutdown rac2
3.停侦听,job process设置为0,kill LOCAL=NO,shutdown rac3
4.保持rac1在线,观察rac 1上的v$transaction、session_wait以及是否出现了smon timer,说明恢复正常。
5.不管是否恢复,在3小时后启动数据库,恢复业务系统。

二、执行情况:
shutdown rac2的时候,近一个小时没有动静。alterlog中:
ALTER DATABASE CLOSE NORMAL
Sat Nov 1 00:28:11 2008
Waiting for smon to disable tx recovery.
Sat Nov 1 01:17:08 2008
Thread 2 advanced to log sequence 46765
Current log# 9 seq# 46765 mem# 0: /ora_redo/redo91
Current log# 9 seq# 46765 mem# 1: /ora_redo/redo92
Sat Nov 1 01:17:08 2008
ARC1: Evaluating archive log 10 thread 2 sequence 46764
ARC1: Beginning to archive log 10 thread 2 sequence 46764
Creating archive destination LOG_ARCHIVE_DEST_1: ‘/arch/gdrac_2_46764.arc’
ARC1: Completed archiving log 10 thread 2 sequence 46764

无奈shutdown abort。
再次启动,正常,再次shutdown immediate。
还是没动静。

看到能shutdown abort后能正常起来,于是决定shutdown abort rac1,再继续按照计划停rac3。

shutdown abort rac2

shutdown immediate rac3,继续无响应。等大半小时。

shutdown abort rac3

观察rac1上的事务和等待,挂死的64号进程仍然存在。数据库中仍有大量的library cache pin和library cache lock和enqueue。

重启rac2和rac2侦听,重启rac3和rac3侦听

恢复业务。

没办法了,不能在最小影响业务的情况下解决该问题,看来要全部节点重启了。

三、后续工作:
目前计划周一(11月3日)晚上重启整个数据库。

【11月4日凌晨,重启3个节点,即重启整个数据库】:

1.23点停rac2侦听
2.checkpoint 3次,switchlogfile 3次,停job query process,shutdown immediate
3.30分钟后仍然没有down,通过oradebug的trace文件看到:
WAIT #1: nam=’instance state change’ ela= 986275 p1=1 p2=0 p3=170
WAIT #1: nam=’instance state change’ ela= 986281 p1=1 p2=0 p3=171
WAIT #1: nam=’instance state change’ ela= 986287 p1=1 p2=0 p3=172
WAIT #1: nam=’instance state change’ ela= 986275 p1=1 p2=0 p3=173
……
4.shutdown abort rac2
5.0点停应用
6.停rac3侦听,停rac1侦听
7.在rac3上checkpoint 3次,switchlogfile 3次,停job query process,shutdown immediate
8.30分钟后仍然没有down,通过oradebug的trace文件看到:
WAIT #1: nam=’instance state change’ ela= 986275 p1=1 p2=0 p3=170
WAIT #1: nam=’instance state change’ ela= 986281 p1=1 p2=0 p3=171
WAIT #1: nam=’instance state change’ ela= 986287 p1=1 p2=0 p3=172
WAIT #1: nam=’instance state change’ ela= 986275 p1=1 p2=0 p3=173
……
9.shutdown abort rac3
10.在rac1上checkpoint 3次,switchlogfile 3次,停job query process,shutdown immediate
11.仍然没有down,通过oradebug的trace文件看到:
WAIT #0: nam=’opishd’ ela= 986314 p1=0 p2=0 p3=0
WAIT #0: nam=’opishd’ ela= 986146 p1=0 p2=0 p3=0
WAIT #0: nam=’opishd’ ela= 986281 p1=0 p2=0 p3=0
WAIT #0: nam=’opishd’ ela= 986285 p1=0 p2=0 p3=0
WAIT #0: nam=’opishd’ ela= 986309 p1=0 p2=0 p3=0
WAIT #0: nam=’opishd’ ela= 986193 p1=0 p2=0 p3=0
WAIT #0: nam=’opishd’ ela= 986278 p1=0 p2=0 p3=0
WAIT #0: nam=’opishd’ ela= 986271 p1=0 p2=0 p3=0
WAIT #0: nam=’opishd’ ela= 986277 p1=0 p2=0 p3=0
WAIT #0: nam=’opishd’ ela= 986306 p1=0 p2=0 p3=0
WAIT #0: nam=’opishd’ ela= 986210 p1=0 p2=0 p3=0
WAIT #0: nam=’opishd’ ela= 986268 p1=0 p2=0 p3=0
……
12.shutdown abort rac1.
13.重启rac1,正常启动
14.重启rac2,正常启动
15.重启rac3,正常启动
16.检查数据库无异常,恢复job query process和侦听。
17.启动业务,进行业务验证。

至此,问题解决。

【经验教训】:

在这个故障上,我们还是可以看到有很多可以汲取的教训:
1.truncate大表的命令尽量不要放在客户端执行,尽量的写成脚本挂在后台跑。
2.truncate过程中如果中断,不要轻易的kill session。
3.truncate大表可以先用dbms_metadata.get_ddl获取索引的建立语句,先drop索引,再truncate大表,再根据ddl语句重建索引。

附:SR的讨论过程。顺便提一句,metalink上的工程师的水平、责任心以及对风险的控制能力,唉……

相关文章

6条评论

  1. 不错的总结! 谢谢!!
    请问你如何做
    11.仍然没有down,通过oradebug的trace文件看到:
    WAIT #0: nam=’opishd’ ela= 986314 p1=0 p2=0 p3=0
    WAIT #0: nam=’opishd’ ela= 986146 p1=0 p2=0 p3=0
    WAIT #0: nam=’opishd’ ela= 986281 p1=0 p2=0 p3=0

    我以前也碰到过长时间down不下来的情况,我一般是检查是不是产生归档,如果产生,则
    可能是一个大的事务在回滚.但有不产生归档的情况.这种情况下如何查什么原因?
    我有时候就先联1个session,查状态,然后用另外一个shutdown,但有时忘了,总的说来,我觉得方法不好,
    请教你的方法?

  2. re hihiw:在shutdown命令敲下去之前,检查自己的spid,然后通过oradebug去进行10046的trace,然后敲下shutdown命令,去看udump下的trace文件。

  3. 我明白了,你仍然是检查自己的session的情况.而我以前的想法主要认为是后台进程有
    什么原因导致down不下去。我以前的理解,shutdown命令发出之后,实际上各后台进程需
    要做各种操作,发出命令的进程则等待,所有执行完成后,协调信息返回发出命令的
    进程.有点类似与commit之后,实际在等待lgwr完成.
    所以追踪自身进程的意义不大.(这是我的理解,)
    或者我的理解有错误?
    我做个实验看看.
    谢谢

  4. 大致看了一下,我的理解是shutdown命令发出后,自身进程需要执行很多步骤,通过监控详细的步骤来推断
    大致原因,我以前过于简单的理解,认为主要的步骤由pmon来执行,其他进程为辅。
    我太想当然了!所以也就没有想trace一下发出命令的进程。
    谢谢!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据