地税某数据库异常重启和重启后数据库运行缓慢问题的解决过程

数据库版本:10.2.0.3

数据库架构:双节点RAC

主机平台:IBM小型机,AIX5.3

这次问题解决过程确认辽宁目前存在2个问题,记录如下:

  第一,数据库实例异常重启。第二,数据库异常重启后造成的整个数据库进行DML操作异常缓慢,直接导致“抽数”时间大幅延长。

  经过深入分析,这2个问题的原因和解决方案如下:


一、数据库实例异常重启

  1、根本原因

  观察jcfx1实例的alert日志发现在18号数据库jcfx1实例自动重启前,发生如下事件,
    
  Mon Oct 18 11:02:06 2010
  Errors in file /app/oracle/admin/jcfx/bdump/jcfx1_smon_753802.trc:
  ORA-00600: internal error code, arguments: [15709], [29], [1], [], [], [], [], []
  ORA-30319: Message 30319 not found; product=RDBMS; facility=ORA
  SMON: terminating instance due to error 474
  Mon Oct 18 11:02:06 2010
  System state dump is made for local instance
  System State dumped to trace file /app/oracle/admin/jcfx/bdump/jcfx1_diag_1699996.trc
  Mon Oct 18 11:02:07 2010
  Shutting down instance (abort)

  即先抛出ora-600事件,然后传递给SMON进程,由SMON进程将实例强制关闭。由于是RAC环境,为了保证高可用性,Oracle clusterware的底层服务又将实例jcfx1启动。给用户的感觉就是数据库实例突然异常重启,其实是jcfx1实例由于600事件自己crash掉了,后又被CRS服务强制启动的结果。为什么会发生这样的问题呢?为什么会出现ora-600事件?根本原因是Oracle的一个未被发布的Bug在做怪,这个Bug平时不被触发,只有当数据库在处理“long transaction”并大量用到Undo段的时候才有可能被触发(而且也不是每次都触发),这个未被发布的Bug的Bug号是“6954722”。

  2、解决方案

  要想数据库实例以后不会再因为Bug6954722触发600事件而重启,有如下3种解决办法,一个是临时救急,另两个是根本解决。临时救急的方法是修改初始化参数“fast_start_parallel_rollback”为“false”,修改“recovery_parallelism”为0。注意,由于只是临时解决方法,并没有根本消除bug,不能保证完全不出现,只能保证出现次数会显著降低,故建议只是短期使用,临时救急。另两个方法,根本解决,一个是打一个“one-off”类型的patch,patch号也是“6954722”;另一个是升级Oracle软件至10.2.0.5。

二、数据库运行缓慢,抽数时间大大延长

  1、根本原因

  这个问题是发生在数据库实例异常宕机并重新启动之后,是属于“数据库异常重启”事件的衍生结果。实例启动以后,整个数据库好像换了个样子,无精打采,除了查询干什么都慢,这是为什么呢?我再看数据库实例启动后的alert日志,如下:
  
  Transaction recovery: lock conflict caught and ignored
  Transaction recovery: lock conflict caught and ignored
  Transaction recovery: lock conflict caught and ignored
  Transaction recovery: lock conflict caught and ignored
  Transaction recovery: lock conflict caught and ignored
  Transaction recovery: lock conflict caught and ignored
           ............
这说明数据库启动后做的各种操作(比如抽数)时不时得在等待其它事务rollback,这些rollback的事务一般来说都是异常中断或者被手工rollback,结合本次案例,显然是由于数据库实例异常重启造成,当时数据库正在进行抽数,有很多大事务正在进行。同时,辽宁的DBA龚工也在现场连接数据库查询动态性能视图V$FAST_START_TRANSACTIONS也发现有3个事务正在rollback,而且需要rollback的量极大,其中一个事务通过查询X$表进行估算竟需要rollback到第15天才能完成。龚工在现场发现的这3个事务也从另一个角度佐证了“数据库运行缓慢”事件的原因。这些正在rollback的事务因为一些锁没有释放,一些事务等待rollback完成,导致很多语句执行效率低,从而阻塞了其它会话。

  2、解决方案

  这些事务如果无法全部rollback,就有可能会造成数据库不一致。所以,除非使用备份恢复,否则唯一的方法就是加快SMON进程对这些事务进行rollback的速度,让它尽快rollback完毕。
  如果数据库允许手工重启,可以采用如下方案提高SMON进程进行rollback的速度:
  第一,待数据库空闲时,将除数据库后台进程外的各种进程全部杀掉,并关闭数据。
  第二,修改初始化参数fast_start_parallel_rollback为false,修改隐藏参数“_cleanup_rollback_entries”为400或者给一个更大的值。
  第三,关闭监听。
  第四,启动数据库。
  第五,等待。
  第六,观察“V$FAST_START_TRANSACTIONS”查看rollback进度,直到事务rollback完毕。
  
  以上方法可以加快SMON进程对事务rollback的速度。
  
  说明:(1)如果数据库不得不执行DML操作且事务依然还没有rollback完毕,也可以先启动监听,一边执行DML操作,一边进行事务rollback,这时事务rollback速度会受到一定程度的影响,DML操作也不快,它相互影响对方的执行速度。(查询业务不会相互影响,任何时候都可以执行查询操作)
     (2)如果有时间、有精力,可以现场测试一下数据库开启并行rollback后的速度,如果测试发现并行rollback比上述方法更快,可以将隐藏参数“_cleanup_rollback_entries”从参数文件去掉并修改fast_start_parallel_rollback为high,然后重启数据库来开启“并行回滚”功能。

 

    数据库在进行实例恢复的时候,有时候时间会很长,可以修改fast_start_mttr_target   为一个限定值如:300

   SQL>startup nomount;

   SQL> alter system set fast_start_mttr_target =300

   SQL> alter database mount;

   SQL>alter database open;

   可以缩短实例恢复的时间,让实例先OPEN,剩下的工作放在后台继续做。

 

posted @ 2010-12-24 17:16  无双的小宝  阅读(2089)  评论(0编辑  收藏  举报