【新书连载】DRM引发RAC的故障分析
编辑说明:《Oracle性能优化与诊断案例精选》出版以来,收到很多读者的来信和评论,我们会通过连载的形式将书中内容公布出来,希望书中内容能够帮助到更多的读者朋友们。
在2015年1月13日凌晨3:44左右,某客户的一套集群数据库的节点1出现crash。检查该节点的告警日志,我们发现了如下内容。
从上述的告警日志来看,在凌晨3:44:43时间点,节点1的LMON进程出现异常被终止,抛出ORA-00481错误。接着节点1的数据库实例被强行终止。
对于Oracle RAC 数据库故障,我们在进行分析时,首先要对OracleRAC的一些核心进程原理有所了解才行,这样才能深入本质。
深入原理
这里我们简单描述Oracle RAC的几个核心进程的基本原理,例如LMON、LMS和LMD等。
Oracle 的LMON进程,其作用主要是监控RAC的GES(Global Enqueue Service)信息。当然其作用不仅仅局限于此,还负责检查集群中各个Node的健康情况。当有节点出现故障的时候,LMON进程负责进行reconfig以及GRD(globalresource Directory)的恢复等。
我们知道RAC的脑裂机制,如果IO fencing是Oracle本身来完成,也就是说由Clusterware来完成。那么当LMON进程检查到实例级别出现脑裂时,会通知Clusterware来进行脑裂操作,当然LMON进程其并不会等待Clusterware的处理结果。当等待超过一定时间,LMON进程会自动触发IMR(instance membership recovery),这实际上也就是我们所说的Instance membership reconfig。
既然提到LMON进程的检测机制,那么LMON如何去检查集群中每个节点的健康状态呢?其中主要分为如下几种。
(1)网络心跳(主要是通过ping进行检测)。
(2)控制文件磁盘心跳,其实就是每个节点的CKPT进程每三秒更新一次控制文件的机制。
Oracle RAC核心进程LMD主要负责处理全局缓存服务(保持块缓冲区在实例间一致)处理锁管理器服务请求。它向一个队列发出资源请求,这个队列由LMS进程处理。同时LMD 还负责处理全局死锁的检测、解析,并监视全局环境中的锁超时(这就是为什么我们经常看到数据库alert log中LMD进程发现全局死锁的原因)。
如果是Oracle11gR2 rac环境,那么还存在一个新的核心进程,即LMBH进程。该进程是Oracle 11R2版本引入的一个进程,该进程的主要作用是负责监控LMD、LMON、LCK和LMS等核心进程,防止这些Oracle核心后台进程spin(stuck)或被阻塞。该进程会定时地将监控的信息打印输出在相应的trace文件中,便于我们进行诊断。这也是11gR2一个亮点。
当LMBH进程发现其他核心进程出现异常时,会尝试发起一些kill动作。如果一定时间内仍然无法解决,那么将触发保护,将实例强行终止掉,当然这是为了保证RAC节点数据的完整性和一致性。
结合案例分析
从上述的日志分析,我们可以看出,节点1实例是被LMON进程强行终止的,而LMON进程由于本身出现异常才采取了这样的措施。那么节点1的LMON进程为什么会出现异常呢?
通过分析节点1数据库实例LMON进程的trace 内容,我们可以看到如下内容。
从上面LMON进程的trace信息来看,LMON进程检测到了DRM在进行sync同步时出现了timeout,最后LMON强制退出了。
既然如此,那么我们应该继续分析为什么DRM会出现timeout。另外根据前面讲述的原理,Oracle DRM的操作主要进程是LMD进程来完成,那么我们来分析节点1实例的LMD进程的trace内容,是否能看出蛛丝马迹。
我们可以看到,当LMON进程遭遇ORA-00481错误之后,LMD进程也被强制abort终止掉了。从LMD 进程的trace文件来看,出现了tickets 等待超时的情况,而且日志中Oracle也告诉我们,在该故障时间点,系统负载并不高。
从上述内容来看,我们似乎并没有得到十分有价值信息。由于LMON进程被强制终止掉之前,触发了一个process dump,因此我们进一步来分析进程dump,继续寻找蛛丝马迹。
LMD进程的processstate dmp 似乎也没有太多有价值的内容。不过我们至少可以肯定的是,系统的资源使用很正常。
通过上述的分析,我们可以看到ORA-00481错误的产生是关键,而这个错误是LMON进程产生的。ORA-00481错误在Oracle MOS文档(1950963.1)中有非常详细的描述,针对本文DRM操作没有结束的情况,一般有如下2种原因。
(1)实例无法获得LE(Lock Elements)锁。
(2)tickets不足。
根据文档描述,我们从数据库两个节点的LMS进程trace中没有发现如下的类似关键信息。
Start affinity expansion for pkey 81885.0
Expand failed: pkey 81885.0, 229 shadows traversed,153 replayed 1 retries
因此,我们可以排除第一种可能性。我们从LMD进程的trace文件中可以看到如下类似信息。
这里的tkt total 表示目前数据库实例总的tickets数据为1000,当前可用的tickets为743. 因此我们可以排除ticket不足的导致DRM没有完成的情况。
换句话讲,上述ORA-00481错误的产生,本身并不是Oracle RAC的配置问题导致。对于LMON进程检查到DRM操作出现超时,最后导致实例崩溃。超时的原因通常有如下几种。
操作系统Load极高,例如CPU极度繁忙,导致进程无法获得CPU资源。
进程本身处理异常,比如进程挂起。
网络问题,比如数据库节点之间通信出现异常。
Oracle DRM Bug。
从上面的信息来看,系统在出现异常时,操作系统的Load是很低的,因此第一点我们可以直接排除。
我们现在的目的是需要分析出LMON进程检查到了什么异常,以及为什么会出现异常。
LMON进程在abort之前进行了dump,那么是否能够从相关dump 中找到一些有价值的线索呢?
...省略部分内容...
从上面LMON进程本身的dump来看,节点1实例的LMON进程状态是正常的,最后发送消息给LMON进程的是SO: 700001405330198,SO即为state obejct。搜索该SO,我们可以发现为LMD进程。
...省略部分内容...
从LMON和LMD进程的process dump来看,进程本身状态是正常的。因此我们可以排除进程挂起导致出现Timeout的可能性。同时我们可以看到LMD进程一直在等待ges remote message,很明显这是和另外一个数据库节点进行通信。
因此我们要分析问题的根本原因,还需要分析节点2数据库实例的一些信息。
首先我们来分析节点2实例的数据库告警日志。
从节点2的数据库告警日志来看,在3:44:48时间点,实例开始进行reconfig操作,这与整个故障的时间点是符合的。
告警日志中本身并无太多信息,我们接着分析节点2数据库实例的LMON进程trace信息。
从上述LMON进程的日志来看,在故障时间点之前,数据库一直存在大量的DRM操作。并且注意到节点进行reconfiguration时,reason 代码值为1。关于reason值,Oracle Metalink文档有如下描述。
从reason =1 来看,数据库实例被强行终止重启也不是通信故障的问题。如果是通信的问题,那么reason值通常应该等于3。reason=1表明这是数据库节点自身监控时触发的reconfig操作。这也与我们前面分析节点1的日志的结论是符合的。
我们从* kjfcln:DRM aborted due to CGS rcfg. 这段关键信息也可以确认,CGS reconfig的原因也正是由于DRM操作失败导致。同时也可以看到,在3:29开始的Begin DRM(82935)操作,一直到3:44出现故障时,这个DRM操作都没有结束(如果结束,会出现EndDRM(82935) 类似关键字)。
由此也不难看出,实际上,该集群数据库可能在3:29之后就已经出现问题了。这里简单补充一下Oracle DRM的原理:
在Oracle RAC环境中,当某个节点对某个资源访问频率较高时,而该资源的master节点不是local节点时,那么可能会触发DRM(Dynamic Resource Management)操作。
在Oracle10gR1引入该特性之前,如果数据库需要更改某个资源的master节点,那么必须将数据库实例重启来完成。很显然,这一特性的引入无疑改变了一切。同时,从Oracle 10gR2开始,又引入了基于object/undo 级别的affinity。这里所谓的affinity,本质上是引入操作系统的概念,即用来表示某个对象的亲和力程度。在数据库来看,即为对某个对象的访问频率程度。
在Oracle 10gR2版本中,默认情况下,当某个对象的被访问频率超过50时,而同时该对象的master又是其他节点时,那么Oracle则会触发DRM操作来修改master节点,这样的好处是可以大幅降低gc grant之类的等待事件。在进程DRM操作的过程中,Oracle会将该资源的相关信息进行临时frozen,然后将该资源在其他节点进行unfrozen,然后更改资源的master节点。
这里我们需要注意的是,这里frozen的资源其实是GRD(Global Resource Directory)中的资源。在整个DRM的过程之中,访问该资源的进程都将被临时挂起。正因为如此,当系统出现DRM操作时,很可能导致系统或进程出现异常的。
实际上关于OracleDRM的Bug也非常多,尤其是Oracle 10gR2版本中。针对本次故障,我们基本上可以认定是如下的Bug导致。
最后建议客户屏蔽Oracle DRM功能之后,经过监控发现运行了相当长一段时间后都没有出现类似问题。
通过这个RAC的案例分析,大家可能注意到,相关的集群日志非常多。在分析过程中,需要保持非常清晰的思路,才能基于问题将这些信息串联起来,最终成为定位和解决问题的重要信息。而事后基于问题的总结和研究,更加是巩固知识、带动我们成长的关键。希望大家能够从中学到故障分析、学习提升的思路和方法。
加入"云和恩墨大讲堂"微信群,参与讨论学习
搜索 盖国强(Eygle)微信号:eyygle,或者扫描下面二维码,备注:云和恩墨大讲堂,即可入群。每周与千人共享免费技术分享,与讲师在线讨论。