十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
春风轻轻吹走了冬日里的寒气,又到了一年最美的花季,伴随着温暖的阳光 老K 再次与大家相见!此次的回归老K不仅会继续和大家分享一些自己处理过的小案例,更优化了技术交流模块,希望在探讨的过程中大家可以提高技术等级的同时,也能领略到中亦DBA团队独有的匠人精神。
发展壮大离不开广大客户长期以来的信赖与支持,我们将始终秉承“诚信为本、服务至上”的服务理念,坚持“二合一”的优良服务模式,真诚服务每家企业,认真做好每个细节,不断完善自我,成就企业,实现共赢。行业涉及成都木制凉亭等,在重庆网站建设公司、成都营销网站建设、WAP手机网站、VI设计、软件开发等项目上具有丰富的设计经验。 问题来了某一日的清晨,客户打来电话称巡检时发现关键系统数据库节点无法连接,原数据库为 4 节点 RAC ,现少一节点,担心业务高峰 3 个节点数据库无法承担业务高峰的压力。这种情况需要尽快处理,所以老 K 选择以最快的远程支持方式解决问题。
问题分析环境描述
系统: linux
数据库:服务器上存在多个数据库实例 p1 和 x1 (此处 p1 和 x1 为化名)
现象描述
本地使用 sqlplus 登录到 x1 数据库发现无法登录到正常状态:
而我 们在本地登录 到 p1 数据库,则一切正常,无明显问题 :
分析步骤小1:查看 alert 日志,了解到数据库从前一天 18 点就开始有报错;
从日志看起来,问题似乎很简单, oracle 运行过程中,组发生了改变:启动时的组为 501 ( oinstall ),当前组却变为了 503 ( asmadmin );同时,我们也可以从 alert 所在目录相关 trace 文件的属性变化来确认这一点:
在 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 这个文件的属主情况:
老 K 在 2 月 10 日查看发现 oracle 文件的属主是 oracle ,属组是 asmadmin ,它的上次修改时间是 12 月 10 日,对比起来相隔久远;然而我们关注的文件属组 / 属主的变化,是不会影响到其显示的修改时间的,只有修改内容或替换文件才会出现文件修改时间的变化。下一步我们就可以使用如图中命令来查看文件属性变化的时间:
显而易见,文件属主 / 属组的改变正是在 2 月 9 日,这样基本全部对应,就可以合理的推断出: oracle 文件的属主在 2 月 9 日发生了变化,随后数据库即产生报错,也就是实际上这个数据库实例自前一天的晚上就不可用了,只是到第二天早上才发现问题,那解决问题的方式就简单多了,重启数据库!因为无法正常登录数据库(连 sysdba 也无法登录),就不得不直接 kill 掉数据库实例的关键进程,然后再正常启动数据库,一切又再次恢复正常。
按照上述步骤分析起来也不是什么麻烦问题,大家或许会想即使我们不懂详细原因,看到数据库没法用了,直接使用重启大法,这个问题不也轻易的就解决了吗?难道还需要理解这个问题的本质吗?
在这里,老K有话说! ↓↓↓↓↓↓↓↓
既然大家选择要走技术的道路,最重要的是保持一颗持久的好奇心,寻找答案的过程予我们也是进益,不断的研究即是不断的提高,永无止境的探索,才是前进路上的唯一指引。当然最重要的是在保证生产环境安全并且合规操作的前提下 !
难题首现
OK ,言归正传我们继续来说问题,前面虽然简述了一些,其实不难发现这里有两个重要的疑问还没有解答 :
为什么 x1 实例存在问题,而 p1 实例却没有受到影响呢?
老 K 首先猜想到的就是:“是不是 p1 实例的启动是在 oracle 文件的属组改变之后呢”?于是查看发现 p1 实例的启动时间:
p1 数据库实例的启动时间是似乎就在 $ORACLE_HOME/bin/oracle 文件的属组改变的前后,这真的是巧合吗?这里引出了第二个疑问
是谁改变了 oracle 文件的属组,为什么要去这么做呢?
如图显示
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 命令呢?
正是因为前一天使用 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 日志:
看到日志老 K 才发现,原来 p1 实例在 12 月 10 号 09:18:09 开始启动,启动到 09:23:33 的时候就已经开始报错,并一直持续到 2 月 9 日重启之前,通过重启的方式最终解决。 P1 为什么会存在这样的问题呢?那么 X1 实例呢,之前为什么没有问题呢?我们再来看看 x1 实例之前的 alert 日志:
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 属组?这里,我们查看了该节点上数据库打补丁的信息,发现自安装以来并没有再打过补丁(日志过长,这里就不再列出);不过很幸运,我们通过历史命令记录查到了蛛丝马迹:之前存在对 oracle 文件的 relink 操作,并将日志记录在了 $ORACLE_HOME/install/relink.log 里,在我们查看 relink.log 的信息时就能定位到这条命令的操作时间了:
基于老 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 实例不可用,因为认为 p 1库不重要,在未核查原因的情况下直接重启了 p1 实例, p1 实例正常 ;
6. 因为在启动 p1 实例是使用的 srvctl start 的命令,导致启动时修改了 $ORACLE_HOME/bin/oracle 的属组,导致 x1 实例不可用 ;
7. 最终通过重启 x1 实例恢复正常。
最后总结:
通过详细的分析,我们发现从 p1 实例的处理方式能很快的解决,但是问题的根本是 有一系列的操作上的失误导致, 所以老 K 想再一次安利下自己的观点:我们在解决问题的过程中,对于任何小疑点都不能轻易滤过,现在发生的问题也许就是由多个小的问题愈演愈烈最终影响正常业务,我们只要对整体分析透彻,自然可以从本质上解决问题。所以大家一定时刻保持探索精神,不忽略任何一个细节,这也是我们作为中亦人一直在坚持的精神!!
好啦,本期就到这里, 今年 我们中亦 DBA 团队将全力以赴,用诙谐和严谨的方式将我们的经验进行分享, 希望大家多多支持,伙伴们的转发分享是对我们大的鼓励!