运维的故事,故障处理系列(一)

出了故障怎么办?老姜在运维行业里面摸爬滚打了这么多年,他的想法就是:“首先快速恢复,然后再分析问题。”对于大型的金融、通信行业的系统来说,一般都有容灾或是应急系统,一旦出了问题,短期无法恢复就直接拉起容灾和应急系统进行切换,用以快速恢复业务的连续性。为何这里这么注重“业务的连续性”,要知道,对于一个通信行业的核心系统来说,几分钟就损失上百万。
而故障的分析,需要我们对各种各样的日志/trace进行搜集,然后再进行分析,找出影响问题的关键。所以故障分析的人员像及了刑事办案人员,对各种蛛丝马迹的信息都要进行逐一排查。故障信息搜集像及了寻找线索,那么我们如何开展线索的搜集呢?

故障有哪些?我们需要搜集什么?
马克思主义哲学有一条指引,就是“具体问题具体分析”,说的就是当我们在遇到事情,想问题的时候,要根据事情的不同情况采取不同的解决办法,不能一概而论。老姜在故障处理方面也深深的懂得这个道理。针对不同类型的故障,需要搜集的日志和Trace信息肯定是不同的。
这里有一个小故事,前段时间公司来了一个新的运维人员,有一天晚上正好是轮到这个新人值班,当时系统出了很严重的latch类的故障,老姜让这个新人收集一些信息过来,结果新人给老姜发的是数据库的alert日志。这让老姜颇为头疼。明显是牛头不对马嘴的一个收集案例。为了好好的规范这个事情,老姜决定亲自整理出一套故障搜集的规范,用于新人和故障分析人员快速的进行有效的沟通。不能总是靠几杆老枪顶着,时不时也需要一些新鲜血液的填充。对运维的新人进行培训也是必须的。
老姜的想法其实和Oracle Support里面的想法类似。首先,新人需要提供现在数据库出问题的一个现象?比如down机了、运行缓慢或者是一些运行报错的错误号、系统的异常等待事件等等?然后针对这个现象,老姜就发给新人发一段搜集信息的代码。新人根据搜集代码进行相关Trace的收集。这个过程非常像Oracle Support开SR和后台人员的一个交流。只不过在运维团队的内部,这个交流是非常顺畅和高效的。同时,老姜认为通过邮件发送到一个故障处理的群组是比较好的。这样,在这个群组里面的人都可以看到,这种考虑是因为一个人的经验值是有限的。大家进行讨论后的结果可能更加准确。在这一点上,老姜一直认为一点,“单打独斗的人是会被淘汰的”,因为在这个多运维的环境里面,科技软件业的发展是很快的,有些时候并不一定是数据库的问题,有可能是存储、主机、网络、应用的某个连锁反应,这时候就需要一个群体,把所有人的智慧结合在一起。团队合作才能更好的把系统的运维理念提升到一个新的高度。
那么摆在老姜面前的难题有那些?
一)尝试进行分类?
试着想一下,我们首先要做的第一件事情就是对故障进行分类。那么故障的种类有很多,比如CRS故障、安装配置、数据恢复、ORA-00600/ ORA-07445等等。为了做到一个健壮的分类,老姜开了一次会,通过历年来遇到的一些问题。分了以下几类进行梳理。

  • 数据库备份与恢复(RMAN,坏块,DUL,BBED);
  • 数据库安装、升级;
  • 数据库测试(SPA和DB REPLAY)
  • 数据库管理配置(内存参数、UNDO、REDO、数据字典、Resource Manager);
  • 数据库性能(查询慢,SQL效率低下,AWR/ADDM报告分析,锁,优化器,并行查询)
  • 数据库、主机Hang;
  • CRS集群软件(自动重启、无法启动,资源异常);
  • 数据库安全类产品(Database Vault,审计,加密);
  • Oracle ASM类故障;
  • ORA-00600/ORA-07445/ORA-04030/ORA-04031类错误;
  • 监听类错误
  • 工具类错误(exp/imp,expdp/impdp,logminer,字符集)
  • 应用程序开发类(SQL,PL/SQL出错);
  • 数据仓库(物化视图,查询重写);

二)根据每一个分类去写故障搜集的脚本?
根据每一个分类去写故障搜集的脚本?这个工作量可想而知,会有非常多的重复内容在里面。例如:数据库遇到ORA-xx错误,我们需要搜集系统Alert日志,还需要搜集相应的Trace文件,遇到另外一个ORA-xx错误,我们又需要搜集系统Alert日志,还有相对应的Trace文件。这不就显得重复了吗?而且老姜也不能保证自己见过所有的故障。所以老姜对这个做法进行了否定。
老姜觉得应该写一个整体的搜集规范的框架,比如这个日志怎么搜集,那个trace怎么搜集。而不应该把每一个问题所对应的搜集办法写出来。因为有些错误,你根本就还没搞明白是什么?需要通过搜集基础的日志来进行判断再分析。所以按照老姜的思路是:列出各种Trace是如何搜集的?搜集工具如何使用的?有了这些就行了。
下一次出现问题后,前台的运维人员(一线监控)发现了故障,及时发邮件出来,描述清楚故障的现象。后台故障人员就把相对应需要搜集的脚本发给运维人员。这样就可以做到哲学里面的“具体问题具体分析了”。

1.老姜的运维经,故障搜集规范
前面我们说到,老姜为了让新进来的员工或者是前台人员能够和专家或者是后台人员能够快速交流,决定制订《故障搜集的规范》,而《故障搜集规范》是一个很庞大的工作,需要对所有的故障有个清晰的了解,但是老姜并不是神,老姜只是一个做了多年运维的老员工,所以老姜想到的办法就是把所有收集信息的办法列到一个文档里面,然后前台人员和后台人员进行初步的交流,然后后台人员把规范里面对应需要搜集的脚本发给前台人员进行搜集。
老姜于是就把需要进行搜集的清单给一一列举,然后他找了几个同事一起开会进行补充。经过2个小时头脑风暴似的会议,大家列举了下面一系列需要搜集的清单。
因为管理的系统都是RAC,单机相对出的问题比较少。所以搜集的规范也是针对RAC系统的。
操作系统日志搜集;
针对不同的操作系统,我们搜集的日志是不相同的。电信行业基本上以AIX/ HP/Solaris/Linux等系统为主,搜集方法如下:

Linux: /var/log/messages
Solaris: /var/adm/messages
HP-UX: /var/adm/syslog/syslog.log
AIX: errpt, errpt –aj

网络相关信息搜集;
有时候我们需要分析是否网络原因导致系统宕机的,通常我们选择使用netstat命令来获取一段时间网卡的整个工作情况。比如发送多少包,接收多少包,有多少是坏包等等。

netstat –s

CRS/GRID日志搜集;
搜集CRS和GRID的日志,一般情况我们是需要进入到CRS_HOME或者是GRID_HOME当中,然后对LOG进行打包。不过Oracle已经为我们想好了更加便捷的办法,那就是使用它自带的diagcollection脚本。
10gR2/11gR1如下:

# script /tmp/diag.log
# id
# env
# cd 
# $GRID_HOME/bin/diagcollection.sh
# exit  

The following .gz files will be generated in the current directory and need to be uploaded along with /tmp/diag.log: 
 
crsData_.tar.gz, 
ocrData_.tar.gz, 
oraData_.tar.gz,
coreData_.tar.gz (only --core option specified)
os_.tar.gz

11gR2/12cR1如下:

# script /tmp/diag.log
# id
# env
# cd 
# $GRID_HOME/bin/diagcollection.sh
# exit  

The following .gz files will be generated in the current directory and need to be uploaded along with /tmp/diag.log: 
 
crsData_.tar.gz, 
ocrData_.tar.gz, 
oraData_.tar.gz,
coreData_.tar.gz (only --core option specified)
os_.tar.gz

提示:收集方法主要参考了 Oracle Clusterware 10gR2/ 11gR1/ 11gR2/ 12cR1 Diagnostic Collection Guide (文档 ID 330358.1)
数据库Alert日志/相关Trace搜集;
基本上所有故障都会考虑进行搜集数据库的Alert日志和Trace,搜集方式如下:

sqlplus / as sysdba
show parameter background_dump_dest
exit;

采集alert日志, Alert中提到的相关的Trace文件,如果是rac的问题,可能还需要采集LMS[0|9] Trace,LCK Trace,LMON trace,LMD Trace,DIAG Trace等等;
HangAnalyze信息搜集;
如果我们的数据库处于Hang住的状态,这个时候最好的办法就是进行Hang Analyze的信息搜集,搜集方式如下:
对单实例搜集:

sqlplus / as sysdba
oradebug setmypid
oradebug unlimit
oradebug hanganalyze 3

对整个RAC实例搜集:

sqlplus / as sysdba
oradebug setmypid
oradebug unlimit
oradebug setinst all
oradebug –g def hanganalyze 3

提示:如果有时候连登陆sqlplus都hang住,可以考虑加-prelim方式进行收集。sqlplus -prelim / as sysdba,不过在11.2.0.2以后的版本,则不能再使用-prelim方式进行搜集。
SystemState信息搜集;
SystemState的跟踪文件包含了现在整个系统中所有进程的状态信息。每一个进程对应一部分的内容,例如:进程的信息,进程的等待事件,队列enqueue的信息,该进程持有及请求其他对象的一些信息。

sqlplus '/ as sysdba'
oradebug setmypid
oradebug unlimit
oradebug dump systemstate 266
====等2-3分钟
oradebug dump systemstate 266
oradebug tracefile_name
exit

另外进行266的采集容易遇到bug 11800959 和11827088,如果没有安装这两个补丁,此时可能会导致系统宕机。这个时候就需要我们使用258的级别来进行采集。
提示: 如果266级别太慢无法生成出来,可以使用258或者是10,10的级别是最快的。关于两个bug的说明:

Bug 11800959 - A SYSTEMSTATE dump with level >= 10 in RAC dumps huge BUSY GLOBAL CACHE ELEMENTS - can hang/crash instances 
Bug 11827088 - Latch 'gc element' contention, LMHB terminates the instance 

ErrorStack/short_stack信息搜集;
使用errorstack和short stack有利于我们对Oracle的错误进行函数堆栈的跟踪。可以帮助我们定位bug。搜集方法如下:

SQL> oradebug setospid 相关进程号
SQL> oradebug unlimit
SQL> oradebug dump errorstack 3
等待2-3分钟左右
SQL> oradebug dump errorstack 3
SQL> oradebug tracefile_name
SQL>exit

如果Error Stack 无法完成,可以考虑使用short_stack.

SQL>oradebug setospid 相关进程号
SQL>oradebug unlimit
SQL>oradebug short_stack
等待2-3分钟左右
SQL>oradebug short_stack
SQL>oradebug tracefile_name
SQL>exit

Core文件搜集及解析;
Core文件一般存放在数据库指定参数CORE_DUMP的目录下面。当我们找到Core文件后,我们需要找到是什么程序产生的Core文件,这个一般可以从Trace里面看到。得知这两个信息后,我们就可以对Core文件进行解析,找出相关的错误堆栈。针对不同的操作系统,我们分析Core文件的方法是不同的。

使用dbx的系统
script /tmp/mystack
dbx $ORACLE_HOME/bin/ core 
(dbx) where
==>Stack should appear here
(dbx) quit
exit
使用gdb的系统
script /tmp/mystack
gdb $ORACLE_HOME/bin/ core
(gdb) bt
==>Stack should appear here
(gdb) thread apply all where
==>Stacks for all threads here
(gdb) quit
exit

提示: 关于Core分析,可以参考文档TECH: Getting a Stack Trace from a CORE file on Unix (NOTE:1812.1)
OS Watcher信息搜集;
Os Watcher主要用来监控主机的资源使用,对于一些数据库异常重启、数据库突然Hang住的诊断非常有帮助。首先我们要进行部署,对于我们所有的生产库,我们都是部署了Os Watcher的。

tar zxvf 解压osw安装文件*.tar.gz
./startOSW.sh 30 168 ==>30秒采集一次,采集7天

这样当出现故障之后,我们就可以直接进入到Os Watcher的Archive目录下面,寻找相对应的IOSTAT/VMWAT/TOP等相关数据了。通过查看主机上的性能数据,有助于帮助我们判断是否资源耗尽引发的数据库Bug。
还需要说明的一点是心跳网络,这个需要自己配置,参考Exampleprivate.net,建立private.net文件,配置类似如下的信息。并给这个文件赋予x权限。

#Linux Example
######################################################################
echo "zzz ***"`date`
traceroute -r -F node1 
traceroute -r -F node2

AWR/ASH/ADDM/Statspack信息搜集;
AWR/ASH/ADDM/Statspack这几种报告,能够在出现性能故障的时候,帮助我们定位是什么原因引起的。

AWR 信息为:
@$ORACLE_HOME/rdbms/admin/awrrpt.sql
ASH信息为:
@$ORACLE_HOME/rdbms/admin/ashrpt.sql
ADDM信息为:
@$ORACLE_HOME/rdbms/admin/addmrpt.sql
STATSPACK信息为:
@?/rdbms/admin/spreport.sql

Process进程信息搜集;
有时候我们需要知道某个进程在运行过程中的状态,比如某个进程内存溢出,使用了过多的内存,这个时候我们可以收集processstate。

SQL> sqlplus / as sysdba
SQL> oradebug setospid 相关进程号
SQL> oradebug unlimit
SQL> oradebug dump processstate 10
等待2-3分钟
SQL> oradebug dump processstate 10
SQL> oradebug tracefile_name
SQL> exit

10046/10053等Event信息搜集;
10046事件可以帮助我们搜集会话在运行过程中,执行了那些SQL,读取了那些块,消耗的时间和资源分别是多少。而10053可以帮助我们分析,执行计划为什么发生了改变,改变的原因是因为统计信息、还是优化器参数等。当然还有一些其他的事件如10020可以帮助我们分析语句逻辑读的情况。

SQL> oradebug setospid 相关进程号
SQL> oradebug unlimit
SQL> oradebug Event 10046 trace name context forever, level 12
SQL> oradebug Event 10046 trace name context off;
SQL> oradebug tracefile_name
SQL> exit

Truss/Strace信息搜集;
进程无法启动、程序突然运行很慢,经常有一些困扰我们的问题,表面上根本就看不出什么问题,此时就需要我们使用Truss和Strace来定位这些疑难杂症。

AIX/Solaris
$truss -aefo   
HP-UX
$tusc -afpo    
Linux
$strace -fo  

提示: 关于Truss/Strace分析,可以参考文档How to Trace Unix System Calls (文档 ID 110888.1)
ASH Dump信息搜集;
有些时候我们需要搜集ASH信息,而这个时候我们的数据库也许正处于Hang的状态,执行ashrpt.sql脚本根本就无法响应。此时就可以使用我们的ASH dump。可以直接从内存中获取到ash的信息。

SQL> oradebug setmypid 
SQL> oradebug unlimit
SQL> oradebug dump ashdump 10
SQL> oradebug tracefile_name
SQL> exit

“上面列出了基本上需要搜集的信息,仅仅有这些够吗?”老姜看了一眼在座的人问道。资深DBA老杨站出来说道:“我们采集的日志没有存储和双机软件的,还有一些特殊的如IPC的信息也可以添加进来”。老姜微微的点了点头说道:“嗯,是的,我们还有一些没有列入到里面,你说的这些我也考虑过,但是我们不是很懂这一方面的知识,就目前的情况来看,我们先把这些基础的形成文档,等以后出现了相关的故障,我们在把这些搜集的方法添加进来,加以完善。其实运维就像是搭建堤坝,首先我们先打好地基,然后再往上面一砖一瓦的进行堆砌,最终我们会把大坝修筑起来,建的越来越宏伟壮观”。老姜握了握拳头,从他深邃的目光中,我们看到了他对故障管理的规范化的坚持。这个世界总有一些人,也许他们不会很快成功,也许一辈子他们都实现不了自己的构想,而且他们在实现自己的想法的时候还会招人奚落取笑,但是他们有足够的勇气,他们相信着自己,老姜就是这样的人,在他的带领下,团队受到了前所未有的鼓舞,大家都开始摩拳擦掌,准备着新一轮和故障的较量。

分享到: 更多

Trackbacks & Pingbacks 1

  1. From 运维的故事,故障处理系列(终结) | Buddy Yuan的个人技术博客 on 23 5月 2020 at 07:11

    […] 运维的故事,故障处理系列(一) 运维的故事,故障处理系列(二) 运维的故事,故障处理系列(三) 运维的故事,故障处理系列(四) 运维的故事,故障处理系列(五) 运维的故事,故障处理系列(六) […]

Post a Comment

Your email is never published nor shared. Required fields are marked *