unable to truncate table

●问题处理总结

故障编号 问题描述 Oracle工作内容 故障/问题解决结果 潜在影响及后续措施计划
db_rac1,db_rac2,db_rac3 生产数据库:
出现应用程序中truncate ,drop table 进程挂起的现象。

Oracle工程师现场分析。 1.Oracle工程师经过仔细分析后,经过与用户协调讨论之后,建议重起数据库。 1. 重起后系统恢复正常。
2. 避免在业务高峰期进行频繁的truncate, drop等动作造成系统阻塞。
3. 可以对数据库SMON进程进行监控,提前进行预警。

2. 背景概述
2.1 故障/问题描述
2.1.1 故障/问题 #1
据客户描述,dbrac1,dbrac2,dbrac3数据库故障,部分truncate,drop table进程挂起。
2.2 故障/问题影响
故障影响部分业务系统的正常运行。
2.3 需要解决的故障/问题
2.3.1 任务 #1

Oracle工程师到达现场后,协助分析问题发生的原因以及恢复方案与实施步骤。

3. 现场处理
3.1 故障/问题 #1
故障描述:
据客户描述,dbra1,dbrac2,dbrac3数据库故障,部分truncate table,drop table进程挂起,业务系统受影响。
原因分析:
故障时间:

由于3个节点都没有运行statspack,所以从I3的历史数据来分析.
从I3的统计报告来看:
在2月14日非正常重起RAC1,RAC2 INSTANCE前的enqueue和dfs lock handle统计数据.
13-feb 7:00—14-feb 6:59
enqueue:wait timeouts times waited
2520k 42728 12.28.09

dfs lock handle :wait timeouts times waited
237119 96 0.2.07

rac2:
13-feb 7:00—14-feb 6:59
enqueue:wait timeouts times waited
2193k 59264 9.41.03

dfs lock handle :wait timeouts times waited
288179 2530 0.29.37

rac3:
13-feb 7:00—14-feb 6:59
enqueue:wait timeouts times waited
2498k 68236 13.35.53

dfs lock handle :wait timeouts times waited
411547 74558 10.20.55

从上面的数据,可以看到enqueue, dfs lock handle的数据基本正常.
但从14日2:00开始各节点的enqueue都比较高.
其中rac3的dfs lock handle比较高,而其发生的时间全部集中在14日1:00到7:00之间.在此期间,应用进行升级.
rac1:
14-feb 11:00—15-feb 10:59
enqueue:wait timeouts times waited
305283 268256 1d,03h

dfs lock handle :wait timeouts times waited
4976 13 0.0.13

rac2:
14-feb 11:00—15-feb 10:59
enqueue:wait timeouts times waited
483989 402727 2d,08h

dfs lock handle :wait timeouts times waited
191017 171848 23.52.09
rac3:
14-feb 11:00—15-feb 10:59
enqueue:wait timeouts times waited
1866k 1315k 7d,14h

dfs lock handle :wait timeouts times waited
175689 169378 23.26.30
而在重起RAC1,RAC2的instance后,enqueue, dfs lock handle等待的时间都有了很大的增加..
从以上的数据可以判断数据库出现问题的时间是在2月14日应用升级和未正常重起数据库后发生.
根据应用方面的说明,在打应用PATCH的时候,所有的应用都被停止.但从I3的统计(14日0:00-5:00)来看,还是有大量的session连接到数据库,并产生大量的REDO日志.特别是RAC3 instance.这可能是由于应用没有完全停止,或者有些CRONTAB,JOB等运行而导致.
在RAC3上可以看到从1:00开始就产生了大量的dfs lock handle等待事件.一般进行truncate操作的时候会导致等待dfs lock handle事件.
由于没有当时的数据,无法判断当时的enqueue的类型以及DFS lock handle在等待的锁的类型.
但根据2月28日的观察,估计14日的enqueue为RO(reuse object)类型的, dfs lock handle为CI,18,5类型,也就是排队重用对象.
smon 10046 trace file:
WAIT #0: nam=’DFS lock handle’ ela= 498034 p1=1128857605 p2=18 p3=5
WAIT #0: nam=’DFS lock handle’ ela= 500052 p1=1128857605 p2=18 p3=5
WAIT #0: nam=’DFS lock handle’ ela= 498016 p1=1128857605 p2=18 p3=5
WAIT #0: nam=’DFS lock handle’ ela= 497974 p1=1128857605 p2=18 p3=5
WAIT #0: nam=’DFS lock handle’ ela= 498033 p1=1128857605 p2=18 p3=5
WAIT #0: nam=’DFS lock handle’ ela= 498078 p1=1128857605 p2=18 p3=5
WAIT #0: nam=’DFS lock handle’ ela= 497963 p1=1128857605 p2=18 p3=5
WAIT #0: nam=’DFS lock handle’ ela= 497811 p1=1128857605 p2=18 p3=5
WAIT #0: nam=’DFS lock handle’ ela= 498000 p1=1128857605 p2=18 p3=5
WAIT #0: nam=’DFS lock handle’ ela= 498003 p1=1128857605 p2=18 p3=5
WAIT #0: nam=’DFS lock handle’ ela= 498056 p1=1128857605 p2=18 p3=5

select chr(bitand(1128857605,-16777216)/16777215)||
chr(bitand(1128857605,16711680)/65535) “Lock” from dual

Lock
CI

也就是RAC1,RAC2,RAC3上的一些需要truncate或drop某个对象的session由于RAC3上某个SESSION的阻塞,而导致等待RO类型的enqueue,而RAC3上的该SESSION在等待dfs lock handle.
而RAC3上该SESSION等待dfs lock handle.,是由于truncate语句需要在所有的instance上扫描 buffer cache,把该对象的CR buffers置为invalidation,并把该对象的dirty block写到硬盘.为了实现这个truncate需要首先获得RO enqueue,然后利用cross-instance call机制,而该CI机制会使用一个global locking protocol来做同步和事件通知.
对不同的global operation,对应的会有不同的CI enqueue.但对于相同的global operation,CI CALL在cluster范围被串行的处理.所以RO enqueue, dfs lock handle都是串行处理的.

在14日进行应用升级期间,可能需要drop,truncate一些对象,或者修改某些对象,而导致其它对象invalid等.象前面分析的那样,在应用升级期间,数据库的3个instance上还有大量的事务在运行.而且数据库的listener也没有停止,还不断的会有应用连上数据库.这样可能会导致潜在的一些重编译而导致对象被加锁,SCAN 各instance buffer cache的时间加长等.

在14日7:00停rac1,rac2 instance前,当前数据库的等待状态为:
RAC1:enqueue高
RAC2:enqueue高
RAC3: dfs lock handle 高,enqueue高
在14日7:00左右分别shutdown rac1,rac2,其日志如下:
RAC1:
Wed Feb 14 07:00:19 2007
Shutting down instance: further logons disabled
Shutting down instance (immediate)
License high water mark = 1145
Wed Feb 14 07:00:24 2007
ALTER DATABASE CLOSE NORMAL
Wed Feb 14 07:05:31 2007
Waiting for smon to disable tx recovery.

Wed Feb 14 08:11:57 2007
Thread 1 advanced to log sequence 4651
Current log# 3 seq# 4651 mem# 0: /ora_redo/redo31
Current log# 3 seq# 4651 mem# 1: /ora_redo/redo32
Wed Feb 14 08:11:57 2007
ARC0: Evaluating archive log 5 thread 1 sequence 4650
ARC0: Beginning to archive log 5 thread 1 sequence 4650
Creating archive destination LOG_ARCHIVE_DEST_1: ‘/arch/db_rac_1_4650.arc’
ARC0: Completed archiving log 5 thread 1 sequence 4650

Wed Feb 14 08:39:20 2007
Thread 1 advanced to log sequence 4652
Current log# 1 seq# 4652 mem# 0: /ora_redo/redo11
Current log# 1 seq# 4652 mem# 1: /ora_redo/redo12
Wed Feb 14 08:39:20 2007
ARC1: Evaluating archive log 3 thread 1 sequence 4651
ARC1: Beginning to archive log 3 thread 1 sequence 4651
Creating archive destination LOG_ARCHIVE_DEST_1: ‘/arch/db_rac_1_4651.arc’
ARC1: Completed archiving log 3 thread 1 sequence 4651
Wed Feb 14 09:02:04 2007
Thread 1 advanced to log sequence 4653
Current log# 2 seq# 4653 mem# 0: /ora_redo/redo21
Current log# 2 seq# 4653 mem# 1: /ora_redo/redo22
Wed Feb 14 09:02:04 2007
ARC0: Evaluating archive log 1 thread 1 sequence 4652
ARC0: Beginning to archive log 1 thread 1 sequence 4652
Creating archive destination LOG_ARCHIVE_DEST_1: ‘/arch/db_rac_1_4652.arc’
ARC0: Completed archiving log 1 thread 1 sequence 4652
Wed Feb 14 09:35:46 2007
Thread 1 advanced to log sequence 4654
Current log# 4 seq# 4654 mem# 0: /ora_redo/redo41
Current log# 4 seq# 4654 mem# 1: /ora_redo/redo42
Wed Feb 14 09:35:46 2007
ARC1: Evaluating archive log 2 thread 1 sequence 4653
ARC1: Beginning to archive log 2 thread 1 sequence 4653
Creating archive destination LOG_ARCHIVE_DEST_1: ‘/arch/db_rac_1_4653.arc’
ARC1: Completed archiving log 2 thread 1 sequence 4653

Wed Feb 14 10:12:48 2007
Thread 1 advanced to log sequence 4655
Current log# 5 seq# 4655 mem# 0: /ora_redo/redo51
Current log# 5 seq# 4655 mem# 1: /ora_redo/redo52
Wed Feb 14 10:12:48 2007
ARC0: Evaluating archive log 4 thread 1 sequence 4654
ARC0: Beginning to archive log 4 thread 1 sequence 4654
Creating archive destination LOG_ARCHIVE_DEST_1: ‘/arch/db_rac_1_4654.arc’
ARC0: Completed archiving log 4 thread 1 sequence 4654

Wed Feb 14 10:46:22 2007
Thread 1 advanced to log sequence 4656
Current log# 3 seq# 4656 mem# 0: /ora_redo/redo31
Current log# 3 seq# 4656 mem# 1: /ora_redo/redo32
Wed Feb 14 10:46:22 2007
ARC1: Evaluating archive log 5 thread 1 sequence 4655
ARC1: Beginning to archive log 5 thread 1 sequence 4655
Creating archive destination LOG_ARCHIVE_DEST_1: ‘/arch/db_rac_1_4655.arc’
ARC1: Completed archiving log 5 thread 1 sequence 4655
Wed Feb 14 10:53:07 2007
Shutting down instance (abort)
License high water mark = 1145
Instance terminated by USER, pid = 2787
Wed Feb 14 10:54:07 2007
Starting ORACLE instance (normal)
Wed Feb 14 10:54:07 2007
Global Enqueue Service Resources = 47110, pool = 16

从RAC1的日志可以看出, 07:00:19 到10:53:07 共切换出3G的日志,而数据库还没有shutdown成功,这说明在数据中有很大的事务还没有执行结束.在shutdown abort后必然有大量的数据要回滚.

RAC2:
Wed Feb 14 07:02:39 2007
Shutting down instance: further logons disabled
Shutting down instance (immediate)
License high water mark = 696
Wed Feb 14 07:07:47 2007
Active call for process 14349 user ‘oracle’ program ‘oracle@gd_rac02 (J004)’
SHUTDOWN: waiting for active calls to complete.
Wed Feb 14 07:18:52 2007
Starting ORACLE instance (normal)

Wed Feb 14 07:26:17 2007
Starting ORACLE instance (normal)
Wed Feb 14 07:36:24 2007
PMON failed to delete process, see PMON trace file
Wed Feb 14 07:45:29 2007
Thread 2 advanced to log sequence 4198
Current log# 8 seq# 4198 mem# 0: /ora_redo/redo81
Current log# 8 seq# 4198 mem# 1: /ora_redo/redo82
Wed Feb 14 07:45:29 2007
ARC0: Evaluating archive log 7 thread 2 sequence 4197
ARC0: Beginning to archive log 7 thread 2 sequence 4197
Creating archive destination LOG_ARCHIVE_DEST_1: ‘/arch/db_rac_2_4197.arc’
ARC0: Completed archiving log 7 thread 2 sequence 4197
Wed Feb 14 08:03:20 2007
SHUTDOWN: Active sessions prevent database close operation

从RAC2的日志来看由于J004 SESSION还在运行当中,而导致RAC2没有SHUTDOWN成功.而PMON并没有清除这些SESSION做占用的资源.
从2月28日观察,该SESSION在OS级别已经被删除,而在数据库级别还存在该SESSION.

从上面的分析可以看出,RAC1有大量的回滚需要做,可能由于不能获得资源而未能执行.RAC2上有session 占用一些资源没有释放.
从2月28日,重起了RAC2的instance,死进程消失.但RAC2的SMON等待RO 类型的enqueue.这说明SMON可能需要重做一些truncate,drop操作,但无法获得RO enqueue.在KILL RAC3上HOLD RO enqueue的session后,RAC2的SMON获得RO enqueue,但等待dfs lock handle.
查看I3的统计,发现从2月14日11点后RAC2,RAC3的dfs lock handle等待时间都非常长:
RAC2:
28日7:00-11:00 3h54m 每小时等待58分钟
RAC3:
28日7:00-11:00 4h08m 每小时等待1小时2分钟

根据ORACLE的TRUNCATE表的串行的算法,一般是不会出现多个等待的dfs lock handle.这可能是由于2月14日RAC2非正常shutdown数据库而导致.
由于RAC3先等待dfs lock handle,所以停止应用,以及JOB后,保证了没有其它的相关TRUNACTE,DROP事务的发生,在重起RAC3 INSTANCE后,它自动回滚相关的事务,并释放相关资源,然后,RAC2,RAC2的SMON会自动回滚相关的事务.

从上面的分析可以看出,本次故障的愿意是由于在应用升级期间,未停止所有的应用,以及未正常的shutdown数据库而导致.

现场分析和处理过程:

a) 检查数据库版本9206上是否存在已知的bug.
b) 制定应急处理措施。
c) 制定解决方案。
d) 测试并观察系统运行情况。

分析:
没有发现9206上存在已知道有关truncate table方面的BUG.
但是从系统稳定性的角度和避免潜在的已知的BUG考虑,建议升级到9208。

应急处理方法和过程:
从数据库观察到db_rac1,db_rac2, db_rac3 三个节点等待事件中 library cache ping.
这些事件的进程的SQL语句都在访问表MONTHCHARGEINFO,MONTHCHARGEINFO_KERNEL.
SELECT A.STATUS,B.ROWID FROM SUBSCRIPTION A, MONTHCHARGEINFO B WHERE A.MID = B.MID AND A.SERVID = B.SERVID AND A.ACCESSMODEID = B.ACCESSMODEID AND A.SERVICEGRADEID= B.SERVICEGRADEID AND A.STATUS!=B.SUBSSTATUS

select LASTFEEMONTH ,STATUS ,ERRORCODE ,ServicePackageId into :b0:b1,:b2:b3,:b4:b5,:b6:b7 from monthchargeinfo_kernel where ((((MID=:b8 and ServId=:b9) and AccessModeId=:b10) and ServiceGradeId=:b11) and subsstatus in (‘A’,’P’))
分析发现,dbrac2上一个进程在truncate table.
SQL> select sql_text from v$sql where address in (select sql_address from v$session where sid=310);

SQL_TEXT
———————————————————————————————-
truncate table MONTHCHARGEINFO_KERNEL

SQL> select * from v$session where sid=310;

SADDR SID SERIAL# AUDSID PADDR USER# USERNAME COMMAND OWNERID TADDR LOCKWAIT STATUS SERVER SCHEMA# SCHEMANAME OSUSER PROCESS MACHINE TERMINAL
—————- ———- ———- ———- —————- ———- —————————— ———- ———- —————- —————- ——– ——— ———- —————————— —————————— ———— —————————————————————- ——————————
PROGRAM TYPE SQL_ADDRESS SQL_HASH_VALUE PREV_SQL_ADDR PREV_HASH_VALUE MODULE MODULE_HASH ACTION ACTION_HASH CLIENT_INFO FIXED_TABLE_SEQUENCE ROW_WAIT_OBJ# ROW_WAIT_FILE# ROW_WAIT_BLOCK# ROW_WAIT_ROW# LOGON_TIM LAST_CALL_ET
———————————————— ———- —————- ————– —————- ————— ———————————————— ———– ——————————– ———– —————————————————————- ——————– ————- ————– ————— ————- ——— ————
PDM FAILOVER_TYPE FAILOVER_M FAI RESOURCE_CONSUMER_GROUP PDML_STA PDDL_STA PQ_STATU CURRENT_QUEUE_DURATION CLIENT_IDENTIFIER
— ————- ———- — ——————————– ——– ——– ——– ———————- —————————————————————-
C0000004436135F0 310 14230 31584426 C000000445638640 45 MISC 0 2147483644 C000000475731A40 C0000004459B5A38 ACTIVE DEDICATED 45 MISC misc16 21135 gd_srv04
monthfeekit@gd_srv04 (TNS V1-V3) USER C000000488533928 2631742473 C00000046ABCEA20 1198893840 monthfeekit@gd_srv04 (TNS V1-V3) 0 0 8359045 1080317 42 0 0 01-MAR-07 33627
NO SELECT BASIC NO DEFAULT_CONSUMER_GROUP DISABLED ENABLED ENABLED 0

SQL> alter system kill session ‘310,14230’;

System altered.
将该truncate table 进程kill,系统恢复。

分析,truncate table 进程挂起的现象,通过系统trace 跟踪,没有发现异常,只是在等待。

数据库重启过程中修改数据库参数并恢复操作步骤如下,
rac3:
SQL> show parameter job
NAME TYPE VALUE
———————————— ———– ——————————
job_queue_processes integer 10

SQL> alter system set job_queue_processes=0 scope=both sid=’db_rac3′;

rac2:
SQL> alter system set job_queue_processes=0 scope=both sid=’db_rac2′;
SQL>alter system set fast_start_parallel_rollback=HIGH scope=memory sid=’db_rac2′;

rac1:
SQL> alter system set job_queue_processes=0 scope=both sid=’db_rac1′;
SQL>alter system set fast_start_parallel_rollback=HIGH scope=memory sid=’db_rac1′;

##############after db restart,recover original parameter.
rac3:
SQL> alter system set job_queue_processes=10 scope=both sid=’db_rac3′;

rac2:
SQL> alter system set job_queue_processes=10 scope=both sid=’db_rac2′;

rac1:
SQL> alter system set job_queue_processes=10 scope=both sid=’db_rac1′;

信息收集方法:
如果发现某个进程执行效率降低,则首先找到该进程的SID,SPID, 然后将该进程打开TRACE。

oradebug setospid
oradebug unlimit
oradebug session_event 10046 trace name context forever, level 12
oradebug tracefile_name(list dump-file name)

oradebug setospid
oradebug unlimit
oradebug session_event 10053 trace name context forever, level 1
oradebug tracefile_name(list dump-file name)

数据库重起后,SMON状态恢复正常后,truncate table,drop table等语句没有发现长时间等待,观察系统运行情况良好。

4. 遗留故障/问题
序号 潜在影响及后续措施计划
故障/问题1 潜在影响:导致
● TRUNCATE DROP TABLE 挂起,应用无法执行
减轻措施:
● 无
急救措施:
● 重起RAC3,RAC2,RAC1,应用正常
后续计划:
● 如上面说的,truncate table会scan data buffer来invalide 包含该对象的数据块,并把dirty buffer放到reuse queue中.而在RAC环境中,如果该对象占用多余一个extent,那就会scan所有的data buffer.其代价是非常高的.此外在RAC中.truncate还需要调用cross-instance call到其它的isntance上去scan 相关的数据块.在10G中,TRUNACATE的性能会很大的提供.对于这种情况,除了保证该对象为1个extent外,temp table并没有太大的帮助.而且在正常的情况下,一般只会带来性能的问题,而不会导致本次的故障现象.
● 本故障于SMON并没有太大关系.SMON都是系统自己做维护的,如果SMON有问题,数据库一定crash.例如本次故障,SMON在等待dfs lock handle,并不是SMON有问题,是由于instance间的锁机制的问题.只要观察数据库,就会发现从2月14日起enqueue和dfs lock handle等待事件在TOP5中.
● 对RAC的维护和普通的数据库维护基本差不多:
● 每天检查数据库的运行状态,等待事件
● RAC需要注意statspack中的”
● Ave receive time for CR block (ms)
● Ave receive time for current block (ms)
一般会小于10ms
● 建议每天运行statspack,并分析报告
● 在应用升级期间,一定要保证没有任何应用所有的连接.可以停止listener,停止数据库,启动数据库.保证一个干净的环境.再进行应用的升级.在升级结束后一定要仔细的检查数据库,不能说应用可以用就没有问题.
● 在shutdown abort数据库后,一定要再进行一次shutdown immediate,保证安全的关闭数据库.

相关文章

2条评论

  1. 能否解释下这句的作用
    alter system set job_queue_processes=0 scope=both sid=’db_rac1′;

    SQL> show parameter job
    NAME TYPE VALUE
    ———————————— ———– ——————————
    job_queue_processes integer 10

    SQL> alter system set job_queue_processes=0 scope=both sid=’db_rac3′;

    rac2:
    SQL> alter system set job_queue_processes=0 scope=both sid=’db_rac2′;
    SQL>alter system set fast_start_parallel_rollback=HIGH scope=memory sid=’db_rac2′;

    rac1:
    SQL> alter system set job_queue_processes=0 scope=both sid=’db_rac1′;
    SQL>alter system set fast_start_parallel_rollback=HIGH scope=memory sid=’db_rac1′;

    ##############after db restart,recover original parameter.
    rac3:
    SQL> alter system set job_queue_processes=10 scope=both sid=’db_rac3′;

    rac2:
    SQL> alter system set job_queue_processes=10 scope=both sid=’db_rac2′;

    rac1:
    SQL> alter system set job_queue_processes=10 scope=both sid=’db_rac1′;

  2. re lifewise:是为了停job,为了避免后续的在停库过程中有job启动,造成active process prevent shutdown progress……

发表评论

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

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