DBA小y
作者DBA小y·2017-07-26 13:44
系统工程师·中亦科技

一次启停引发的故障

字数 5039阅读 1207评论 1赞 6

春风轻轻吹走了冬日里的寒气,又到了一年最美的花季,伴随着温暖的阳光老K再次与大家相见!此次的回归老K不仅会继续和大家分享一些自己处理过的小案例,更优化了技术交流模块,希望在探讨的过程中大家可以提高技术等级的同时,也能领略到中亦DBA团队独有的匠人精神。
问题来了

某一日的清晨,客户打来电话称巡检时发现关键系统数据库节点无法连接,原数据库为4节点RAC,现少一节点,担心业务高峰3个节点数据库无法承担业务高峰的压力。这种情况需要尽快处理,所以老K选择以最快的远程支持方式解决问题。

问题分析
环境描述
系统:linux
1.png

1.png

数据库:服务器上存在多个数据库实例p1和x1(此处p1和x1为化名)
2.png

2.png

现象描述
本地使用sqlplus登录到x1数据库发现无法登录到正常状态:
3.png

3.png

而我们在本地登录到p1数据库,则一切正常,无明显问题:
4.jpg

4.jpg

分析步骤小1:
查看alert日志,了解到数据库从前一天18点就开始有报错;
5.jpg

5.jpg

6.jpg
6.jpg

7.jpg
7.jpg

从日志看起来,问题似乎很简单,oracle运行过程中,组发生了改变:启动时的组为501(oinstall),当前组却变为了503(asmadmin);同时,我们也可以从alert所在目录相关trace文件的属性变化来确认这一点:
8.jpg
8.jpg

在18:43产生或更新的trace文件还是oracle:oinstall的属主,而到了18:44,新产生或更新的trace文件便成了oracle:asmadmin属主。

知识点:
问:在UNIX/LINUX环境中,oracle数据库启动后存在许多后台进程和前台进程,虽然相关进程产生一些trace文件也是常有的事情,但是真正是什么决定了oracle相关进程的属性呢?
答:通常来说,oracle的后台进程的调用是依赖于$ORACLE_HOME/bin/oracle这个二进制文件,但它从远端连入而分配的服务器进程(server process)相关属主的属性则是继承自listener进程,而listener进程的属主属性同样是进程自其启动的用户(分oracle用户和grid用户)$ORACLE_HOME/bin/oracle的属主属性。

分析步骤小2:
这样,我们就可以查看$ORACLE_HOME/bin/oracle这个文件的属主情况:
9.png

9.png

老K在2月10日查看发现oracle文件的属主是oracle,属组是asmadmin,它的上次修改时间是12月10日,对比起来相隔久远;然而我们关注的文件属组/属主的变化,是不会影响到其显示的修改时间的,只有修改内容或替换文件才会出现文件修改时间的变化。下一步我们就可以使用如图中命令来查看文件属性变化的时间:
10.jpg

10.jpg

显而易见,文件属主/属组的改变正是在2月9日,这样基本全部对应,就可以合理的推断出:oracle文件的属主在2月9日发生了变化,随后数据库即产生报错,也就是实际上这个数据库实例自前一天的晚上就不可用了,只是到第二天早上才发现问题,那解决问题的方式就简单多了,重启数据库!因为无法正常登录数据库(连sysdba也无法登录),就不得不直接kill掉数据库实例的关键进程,然后再正常启动数据库,一切又再次恢复正常。
按照上述步骤分析起来也不是什么麻烦问题,大家或许会想即使我们不懂详细原因,看到数据库没法用了,直接使用重启大法,这个问题不也轻易的就解决了吗?难道还需要理解这个问题的本质吗?
在这里,老K有话说!↓↓↓↓↓↓↓↓

   既然大家选择要走技术的道路,最重要的是保持一颗持久的好奇心,寻找答案的过程予我们也是进益,不断的研究即是不断的提高,永无止境的探索,才是前进路上的唯一指引。当然最重要的是在保证生产环境安全并且合规操作的前提下!

难题首现

  OK,言归正传我们继续来说问题,前面虽然简述了一些,其实不难发现这里有两个重要的疑问还没有解答:

为什么x1实例存在问题,而p1实例却没有受到影响呢?
老K首先猜想到的就是:“是不是p1实例的启动是在oracle文件的属组改变之后呢”?于是查看发现p1实例的启动时间:
11.png

11.png

    p1数据库实例的启动时间是似乎就在$ORACLE_HOME/bin/oracle文件的属组改变的前后,这真的是巧合吗?这里引出了第二个疑问

是谁改变了oracle文件的属组,为什么要去这么做呢?
12.jpg

12.jpg

如图显示p1实例的trace文件也曾在2016年的12月10日发生过改变,而且改变后,一直保持为oracle:oinstall的属主属性,而在2月9日重启完成后恢复为oracle:asmadmin的属主属性(图片中没有显示出来),也就是说在更早之前,我们可以推断$ORACLE_HOME/bin/oracle文件的属组是asmadmin,在12月10日更改为oinstall,而在2月9日再次更改为asmadmin。

老K的回忆沙龙~
事情似乎又变的复杂起来了,这里让老K想起遇到过的一段经验,CASE是这样的:我们在打完数据库补丁之后,经常会出现$ORACLE_HOME/bin/oracle文件的属组发生改变,导致本地的非dba用户不通过监听连接数据库时报无法访问ASM磁盘的情况(asm磁盘的属组一般是grid:asmadmin的),而我们只需要通过使用srvctl start database 的方式来重新启动数据库就可以解决该问题(当然在数据库停止的情况下直接chown的方式也可以);
那么在这个问题里是不是也前一天重启p1实例也是用的srvctl命令呢?
13.jpg

13.jpg

正是因为前一天使用srvctl的方式启动了p1节点,改变了oracle文件的属组,导致了x1节点出现报错;至于为什么要改变oracle文件的属组,那就是oracle的机制的原因了。这里我们需要理解的一点,使用srvctl/crsctl命令来启停数据库和使用sqlplus登录到数据库中启停数据库的区别是,srvctl/crsctl命令调用的是crs中oraagent来执行的,而sqlplus是在oracle用户下直接执行的。

小结

  1. 数据库实例p1和x1在正常运行;
  2. $ORACLE_HOME/bin/oracle文件的属组是oinstall的;
  3. 2月9日,运维人员重启了p1实例,启动时的方式是srvctl startinstance -d p -i p1,这个过程中将$ORACLE_HOME/bin/oracle的属组改为asmadmin;
  4. 数据库实例x1开始报错运行时属组与启动时属组不一致。

难题再现!
到这里,前面的两个难题已经解开,不过我们在与客户的沟通过程中就不免多问一句,为什么会去重启p1实例呢?给出的答案又引起了我们的思考:前一天客户发现p1实例无法登录,由于p1数据库实际上已经不作生产使用,平时可能会有一些简单的测试使用到这个数据库,所以客户的现场维护人员直接重启了p1实例解决问题。但是为何p1实例会无法登录呢?如果仅仅是测试库的话,正常是不应该有压力大的情况,还是说也是类似x1的情况?就此,我们再从分析p1实例之前的运行情况。另外,从前面的过程来看,我们可以看到oracle文件属组曾经从asmadmin变为oinstall,这样我们就还需要解释一个问题,如果说srvctl的方式启停数据库会将$ORACLE_HOME/bin/oracle文件的属组改为asmadmin的话,那么,又是什么让这个文件的属组改为oinstall的呢?带着这两个新的疑惑,老K再次踏上解惑的征程,先来看p1实例的alert日志:
15.jpg

15.jpg

16.jpg
16.jpg

17.jpg
17.jpg

18.jpg
18.jpg

看到日志老K才发现,原来p1实例在12月10号09:18:09开始启动,启动到09:23:33的时候就已经开始报错,并一直持续到2月9日重启之前,通过重启的方式最终解决。P1为什么会存在这样的问题呢?那么X1实例呢,之前为什么没有问题呢?我们再来看看x1实例之前的alert日志:
19.png
19.png

20.jpg
20.jpg

21.jpg
21.jpg

      x1实例在启动时也经历过启动报错的过程,只不过很不幸,x1实例在启动后台进程RSMN时,就已经出错,导致实例启动失败,而后在09:23再次启动,则启动成功,后续因为$ORACLE_HOME/bin/oracle文件没有修改过属组,直到2月9日18点,也没有再报过错。细心的同学可以看到 x1实例和p1实例在12月10日的shutdown和初次startup的时间是基本一致的,于是我们猜测,这个动作应该是使用crsctl stop crs和crsctl start crs的方式来启停CRS的过程中顺带将数据库启停了,那么为什么p1实例启动完成了,而x1实例启动失败了呢?事实上这里p1也就只是启动了实例,并没有打开数据库,而x1实例启动失败是因为其关键进程RSMN的启动时间正好在$ORACLE_HOME/bin/oracle的属组修改的时间(09:19:22)之后导致启动失败,而再次启动时,x1实例相关进程的属组也就都一致了不再存在启动时和运行时属组不一致的问题了。

现在,我们还剩下最后一个难题,那就是12月10日,客户现场的维护人员做了什么才导致$ORACLE_HOME/bin/oracle文件的属组变为了不正确的oinstall属组?这里,我们查看了该节点上数据库打补丁的信息,发现自安装以来并没有再打过补丁(日志过长,这里就不再列出);不过很幸运,我们通过历史命令记录查到了蛛丝马迹:
22.png

22.png

之前存在对oracle文件的relink操作,并将日志记录在了$ORACLE_HOME/install/relink.log里,在我们查看relink.log的信息时就能定位到这条命令的操作时间了:
23.png
23.png

基于老K日常积累的经验,才可以这么认定relink操作就会改变oracle文件的属组信息。在opatch打完一些数据库补丁后,通常会改变oracle文件的属组信息,如果我们细看opatch过程中的详细日志,我们就会发现,这个过程中实际上使用的底层命令就是relink,也就认为relink实际上会修改oracle文件的内容,同时也会修改oracle文件的属组(因为做这个操作的用户是oracle:oinstall)。得出结论后继续与客户进行沟通,对话如下:↓↓↓↓↓

现场运维商确实在之前处理其它问题时,使用过relink命令重现编译oracle文件,但是当时没有启动数据库。
是不是当时先重启了操作系统呢?

请输入

厄。。。好像是的!

到底发生了什么?
1.12月10日,客户的现场运维商需要使用relink命令解决问题;
2.在relink之前直接重启操作系统,操作系统启动时,自动启动CRS,并且将试图启动数据库以恢复到之前状态
3.在启动数据库的过程中,维护商没有关注到是否有数据库正在运行即已开始执行relink操作;
4.在relink操作的过程中,p1完成了实例启动,而x1实例则因为RSMN启动时oracle文件的属组已经发生改变,RSMN启动失败,继而导致x1实例失败,而p1实例虽然启动成功,但是一直报错,数据库也未能打开;
5.在此期间p1实例实际上是不可用的,在2月9日维护商发现p1实例不可用,因为认为p1库不重要,在未核查原因的情况下直接重启了p1实例,p1实例正常;
6.因为在启动p1实例是使用的srvctl start的命令,导致启动时修改了$ORACLE_HOME/bin/oracle的属组,导致x1实例不可用;
7.最终通过重启x1实例恢复正常。

最后总结:
通过详细的分析,我们发现从p1实例的处理方式能很快的解决,但是问题的根本是有一系列的操作上的失误导致,所以老K想再一次安利下自己的观点:我们在解决问题的过程中,对于任何小疑点都不能轻易滤过,现在发生的问题也许就是由多个小的问题愈演愈烈最终影响正常业务,我们只要对整体分析透彻,自然可以从本质上解决问题。所以大家一定时刻保持探索精神,不忽略任何一个细节,这也是我们作为中亦人一直在坚持的精神!!
好啦,本期就到这里,今年我们中亦DBA团队将全力以赴,用诙谐和严谨的方式将我们的经验进行分享,希望大家多多支持,伙伴们的转发分享是对我们最大的鼓励!

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

6

添加新评论1 条评论

macroseamacrosea项目总监人民医院
2017-08-01 12:36
透过现象看本质,不错
Ctrl+Enter 发表

作者其他文章

相关文章

相关问题

相关资料

X社区推广