案例:smon回滚异常导致实例crash

某省电力系统的一个4节点rac,2节点在早上的时候crash。

当smon重新发起并行回滚时,实例被pmon终止,这里有一个隐藏错误,常常被忽视,PMON (ospid: 100111): terminating the instance due to error 474

说明是pmon发现smon异常而终止的实例。那么看看smon trace文件

smon在重新发起回滚时异常之后进程被crash了,最终pmon终止了实例。继续往前查看alert日志发现从6点52分46秒开始报一些异常之后,就开始了blockrecover并伴随一些ora-00600[4193]错误。

对于ora-00600[4193],经常搞恢复的太熟悉不过了。不过一般在异常断电强制open数据库的时候遇到,正常运行的环境很少见,其含义如下:

其实质就是ktubhseq和ktudbseq不一致,如果是ktudbrec和ktubhcnt不一致则为ORA-00600[4194],ktubh是undo block中的结构,ktudb是redo记录undo块操作时会记录的信息。

回到案例,从trace中可以看到ktubh和ktudb的信息。

ktudb记录如下:

  • xid: 0x750f.003.0093843a
  • uba: 0x1cd49528.ddee.01
  • seq: 0xddee
  • rec: 0x02

uba指向的undo块ktudb信息如下:

  • xid: 0x750d.009.00abc7f4
  • seq: 0xd24
  • cnt: 0x4d

这里看到undo块中已经有一个活动事务了,这就不仅仅是seq不一致的问题了,更严重的是一个新事务居然去找了一个存在活动事务的undo块来使用。我们知道undo段头会预分配最多5个block到free block pool里作为下一个事务准备,当需要分配undo块时,会去寻找free block pool里面的块。看看报错事务指向的undo段头块(段头号为0x750f)

可以看到free block pool里有一个块正好是0x1cd49528。综上所述,undo块0x1cd49528实际已经分配给undo段头0x750d,并且已经有事务xid: 0x750d.009.00abc7f4正在使用该undo块,但是undo段头0x750f里面的FREE BLOCK POOL并没有把这个块清理掉,导致了ORA-00600[4193]产生。

一般对于事务异常的问题会触发blockrecover操作,那6点52分46秒就出现了blockrecover,是否问题就是从这里开始的呢?pmon trace显示blockrecover是从6点52分49秒开始,file 2608 block 144即为undo段头0x750f的块地址,

从一些前台进程trace里可以看到,6点52分51秒的事务TX-750F0003-0093843A就已经无法进行。进程被crash。

该事务id和之前分析报错的ORA-00600[4193]是一样的。说明从6点52分46秒开始,undo段头0x750F就无法绑定事务了,原因就是free block pool里的undo块已经不属于该undo段了,被事务0x750d.009.00abc7f4使用了。通过redodump可以验证这一点。

该undo块一系列操作都是在11/03/2021 06:52:46完成,这明显不符合undo块分配原则,怀疑是bug,但是mos没有找到类似文档

  • SCN: 0x0eaa.692b839b,undo块0x1cd49528分配给到undo段头地址为0x8c800090的undo段(段头号为0x750f)
  • SCN: 0x0eaa.692b8484,undo块0x1cd49528分配到undo段头地址为0x8c800080的undo段(段头号为0x750d)
  • SCN: 0x0eaa.692b84b8,事务0x750d.009.00abc7f4使用了该undo块

undo块分配原则:

综上分析我们得到的解决办法有如下几种

  • 重建该实例的undo表空间
  • 删除异常的undo段(段头号为0x750f)
  • bbed清空undo段(段头号为0x750f)的free block pool

那么故障的原因和解决方案分析完了,还有一个很异常的问题,就是为什么几乎同一时间undo块连续分配给两个undo段,而且当undo block分配给其他undo段使用的时候,为什么以前的undo段的free block pool里没有清理掉呢?结合当时的awr来看有比较严重的undo争用,undo extent steal也很频繁,再往前翻看alert发现频繁的ORA-01628

我怀疑是频繁的undo extent扩展、收缩、偷取导致的undo块分配紊乱。由于没有对系统平时的负载做分析,这里暂时先给出一些粗略的后续建议:

  • undo设置为undo retention guarantee
  • 合理设置undo相关参数
  • 合理设计事务,避免大事务产生
  • 分析dba_undo_extents,很可能有过多的非常小的undo extent

 

此条目发表在Oracle, Oracle troubleshooting分类目录,贴了, 标签。将固定链接加入收藏夹。

发表回复

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