美国上市公司,专注Java培训21年

故障树分析法在数据库诊断分析中的应用


编辑手记:将知识转化为能力,除了需要经验的积累和时间的磨砺,更重要的是正确的方法和思维模式,学会应用知识才是真正的能力。本文试图通过方法的讨论使大家能够形成一个稳定的解决问题的思路和方法,按照这个思路和方法将我们所学的知识整理武装起来,这样在面对问题时就能够快速地找到一条发现和解决问题之路。

故障树分析法

(Fault Tree Analysis,FTA)是在对系统的可靠性进行分析时最常用的方法之一。FTA方法是指在系统设计或改进过程中,通过对可能造成系统故障的各种因素(包括硬件、软件、环境、人为因素等)进行分析,画出逻辑框图(即故障树),从而确定系统故障原因的各种可能组合方式及其发生概率,并以此计算系统的故障概率,采取相应的措施,以提高系统可靠性的一种设计分析方法和评估方法。

故障树分析图经常被用在Six Sigma进程中,特别用在Six Sigma业务改进进程的分析阶段。

故障树分析法对于数据库故障解决的意义

经过在实践和应用中的总结,我发现故障树分析法作为一种分析方法和思路,同样适合数据库故障的分析和解决,如果扩展一步来说,这种方法作为一种思维方式,甚至适合生活中所有事件的分析和处理。

但是需要注意的是,故障分析实际上是一种事后分析的方法,当然我们不希望工作、生活中当事故、问题出现后再来分析,所以,我一直提倡将故障树分析在事前实施,通过参考别人的经验、教训,将故障树引入事前,人类的学习特点应当能够使我们从学习中而不是亲身经历去获得经验。

通过实践我们发现,将应用于传统行业的故障树分析法引入到数据库故障分析及问题解决之中,可以极大地加快问题分析、处理和解决的速度,同时可以帮助我们发现系统的缺陷所在,从而通过实施有效的预防措施显著地提高系统的稳定性和可靠性。

故障树分析模型的建立

如图所示是数据库系统故障分析树的一个示例,这里以数据库故障为起点,来分析可能导致数据库及应用故障的可能因素。

故障树分析法在数据库诊断分析中的应用

分析的过程是一个穷举故障原因的过程,我们可以按照不同的方法对故障的原因进行分类,在这个分析中,首先我将第一层归结为3类问题:客户端/中间层故障、网络故障、服务器端故障。这其中任何一处出现问题都可能会导致数据库服务出现问题。

再来进一步深入分析,在一个数据库系统中,客户端或中间层如果出现问题,就可能会影响数据库系统的使用,但这在用户看来同样是数据库故障。那么对于这一类问题,进一步细分,客户端/中间层有哪些故障会引起数据库的访问不畅呢?

首先如果客户端的应用程序损坏可能造成数据库的无法连接,曾经有很多案例因为客户端感染病毒而导致应用程序异常;然后常见的还有客户端版本及驱动问题,Oracle的版本众多,如果驱动版本不匹配可能也会出现问题;客户端的防火墙有时候也会成为阻碍数据库成功访问的障碍之一;当然更为常见的是客户端的配置文件(tnsnames.ora文件或中间件的配置文件)存在问题,导致无法正确连接数据库的。可能的原因还有很多,更为完善的故障树分析图如下图所示。

【故障树分析法在数据库分析诊断中应用】

分析完客户端,在数据库和客户端之间还存在网络,网络问题也是常见数据库故障的问题点之一,可以尝试对网络故障再进行细分,如下图所示。

网络故障的可能原因也很多,首先是物理链路的问题,公网和内网都可能存在链路故障、品质降低等,再加上地址路由等因素,这方面的故障实在很多见,其次防火墙、带宽、流量等因素也是需要考虑的。

【故障树分析法在数据库分析诊断中应用】

当客户端、网络一切正常之后,就到了最重要的一环──数据库服务器端,如果这里出现故障或性能问题,那么原因可能是极其复杂和多样化的。下图列举了一些常见的数据库端故障问题,这张故障分析图是应该存储在每个DBA的头脑中的。

【故障树分析法在数据库分析诊断中应用】

首先客户端经过网络向数据库发送请求,数据库服务器端最先接受请求的数据库监听器,如果监听器出现问题,则数据库连接肯定会出现异常,所以监听器是一个重要环节和故障点。

数据库服务器还可能会经常出现资源短缺等问题,比如连接数耗尽、用户无法创建新的连接;因为归档或备份,磁盘空间可能被耗尽,导致数据库问题;或者磁盘I/O因为硬件故障或性能问题,都可能导致数据库故障或响应缓慢;内存资源或交换也是重要内容,如果内存不足,可能导致数据库性能低下,严重影响数据库的正常运行;CPU资源不足是实际生产中经常会遇到的问题,其原因多样化,可以沿这个节点进一步深入分析。

此外,应用问题也是经常会导致故障的原因之一,有的是因为SQL编写问题,有的是因为数据结构设计存在问题,有的甚至是数据库软件本身就存在Bug。最后来看一下这张图的全貌。

【故障树分析法在数据库分析诊断中应用】

事实上,故障树分析法的使用完全可以十分灵活,我们可以以任何一个提出的问题作为分析起点,比如用户经常反映“数据库响应缓慢”的问题,就可以从这里出发进行问题分解和分析。

【故障树分析法在数据库分析诊断中应用】

有了这样的分析基础之后,在遇到故障时就可以快速地在大脑里进行根据故障树进行分析导航,从而迅速地定位问题的原因,并根据经验或知识找到解决故障的方法。从这个意义上说,故障树也是一个索引。

在这篇文章的讨论过程中,曾经有专家问过我这样的问题:你这种方法只是一个理论的设想,还是在实际中能够有所应用?

实际上我在故障处理中一直是按这样一个思路在处理,后来当我思考怎样将思路转化为方法更容易为大家所学习、探讨时,发现了故障树分析法;我发现故障树分析法就正是我一贯的思维方式,两者契合得如此之好,所以我才将这种方法总结出来供大家参考。

故障树分析法在故障解决中的应用

接下来我们通过一个案例来讨论一下故障树分析法在实际问题解决中的应用。这是一个24×7的重要业务系统,故障出现时业务及开发人员报告系统运行缓慢,已经影响业务系统正常使用,请求协助诊断。

性能缓慢到CPU消耗的定位

业务系统缓慢,根据我们的故障树,可能的原因有资源耗尽、应用问题等,在实际环境中,很多问题可能是同时出现和产生影响的。

首先登录数据库主机,检查当前系统状况。使用vmstat检查,发现CPU资源已经耗尽,大量任务位于运行队列:

【故障树分析法在数据库分析诊断中应用】

本案例当时,系统CPU资源已经耗尽,Idle为0,并且运行队列大量进程排队等待。通过故障树分析思路,利用简单的系统工具辅助,很快就可以发现问题的症结所在。进一步地,我们可以检查一下进程问题,CPU资源的过度耗用可能是个别进程异常或者进程过量累积所导致的。

CPU到进程的故障树分析

通过Top工具,我们可以查看进程CPU耗用情况,如果存在进程异常,可以通过Top定位,为进一步诊断提供依据。对于本案例,观察进程CPU耗用,发现没有明显过高CPU使用的进程。

【故障树分析法在数据库分析诊断中应用】

从Top的输出中,可以发现有大量进程处于running的运行状态,CPU消耗很平均,单进程消耗大约在1%左右,基本可以排除个别进程异常导致CPU问题的可能。没有个别进程异常,那么过量的CPU消耗可能是进程累积所导致的,我们根据故障树,在同一层面上对可能导致CPU过度消耗的原因进行排查。我们知道对于一个生产数据库系统,稳定运行的进程数量通常是可知的。

提示:对于稳定运行的生产系统,数据库的运行状况通常是稳定的,如果你绘制出性能曲线,你会发现每个星期的曲线几乎是可以重合的,所以说对数据库系统的运行状况及性能指标具有充分认识和了解是必须的。

来看一下当前系统的进程数量,从而进行比较判断:

bash-2.03$ ps -ef|grep ora|wc -l

258

bash-2.03$ ps -ef|grep ora|wc -l

275

bash-2.03$ ps -ef|grep ora|wc -l

274

bash-2.03$ ps -ef|grep ora|wc -l

278

bash-2.03$ ps -ef|grep ora|wc -l

277

bash-2.03$ ps -ef|grep ora|wc -l

366

发现此时系统存在大量Oracle进程,大约在300左右,大量进程消耗了几乎所有CPU资源,而正常情况下Oracle连接数应该在100左右。

由此,可以基本判断,是数据库或应用出现了问题导致进程任务无法完成,又不断累积,从而出现大量队列等待。这些等待在数据库中应该有具体的体现,接下来需要登录数据库进行检查了。

进一步诊断应用问题

判断数据库可能经历了等待,那么Oracle数据库提供了相关视图供我们查询和发现问题,v$session_wait是首先值得关注的。查询v$session_wait获取各进程等待事件:

【故障树分析法在数据库分析诊断中应用】

对于本案例,我们发现存在大量db file scattered read及db file sequential read等待。显然全表扫描等操作成为系统最严重的性能影响因素。确定这些进程因为数据访问产生了等待,我们考虑捕获这些SQL以发现问题。

这里用到了我的以下脚本getsqlbysid.sql,该脚本通过已知session的sid,联合v$session、v$sqltext视图,获得相关session正在执行的完整的SQL语句。

SELECT sql_text

FROM v$sqltext a

WHERE a.hash_value = (SELECT sql_hash_value

FROM v$session b

WHERE b.SID = '&sid')

ORDER BY piece ASC

/

使用该脚本,通过从v$session_wait中获得的等待全表或索引扫描的进程SID,可以捕获可能存在问题的SQL语句:

SQL> @getsqlbysid

Enter value for sid: 18

old 5: where b.sid='&sid'

new 5: where b.sid='18'

SQL_TEXT

----------------------------------------------------------------

select i.vc2title,i.numinfoguid from hs_info i where i.intenab

ledflag = 1 and i.intpublishstate = 1 and i.datpublishdate <=

sysdate and i.numcatalogguid = 2047 order by i.datpublishdate d

esc, i.numorder desc

SQL> /

Enter value for sid: 54

old 5: where b.sid='&sid'

new 5: where b.sid='54'

SQL_TEXT

----------------------------------------------------------------

select i.vc2title,i.numinfoguid from hs_info i where i.intenab

ledflag = 1 and i.intpublishstate = 1 and i.datpublishdate <=

sysdate and i.numcatalogguid = 33 order by i.datpublishdate des

c, i.numorder desc

......

对几个进程进行跟踪,分别得到以上SQL语句,这些SQL可能就是问题产生的根源。

从SQL到问题本质的诊断

使用该应用用户连接,通过autotrace功能检查以上SQL的执行计划:

SQL> set autotrace trace explain

SQL> select i.vc2title,i.numinfoguid

2 from hs_info i where i.intenabledflag = 1

3 and i.intpublishstate = 1 and i.datpublishdate <=sysdate

4 and i.numcatalogguid = 3475

5 order by i.datpublishdate desc, i.numorder desc ;

Execution Plan

----------------------------------------------------------

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=228 Card=1 Bytes=106)

1 0 SORT (ORDER BY) (Cost=228 Card=1 Bytes=106)

2 1 TABLE ACCESS (FULL) OF 'HS_INFO' (Cost=218 Card=1 Bytes=106)

SQL> select count(*) from hs_info;

COUNT(*)

----------

227404

通过执行计划,可以看到以上查询使用了全表扫描,而该表这里有22万记录,全表扫描已经不再适合。检查全表扫描的数据表,发现存在以下索引:

SQL> select index_name,index_type from user_indexes where table_name='HS_INFO';

INDEX_NAME INDEX_TYPE

------------------------------ ---------------------------

HSIDX_INFO1 FUNCTION-BASED NORMAL

HSIDX_INFO_SEARCHKEY DOMAIN

PK_HS_INFO NORMAL

检查索引键值:

SQL> select index_name,column_name

2 from user_ind_columns where table_name ='HS_INFO';

INDEX_NAME COLUMN_NAME

------------------------------ --------------------

HSIDX_INFO1 NUMORDER

HSIDX_INFO1 SYS_NC00024$

HSIDX_INFO_SEARCHKEY VC2INDEXWORDS

PK_HS_INFO NUMINFOGUID

SQL> desc hs_info

Name Null? Type

--------------------------------- -------- --------------------------------------------

NUMINFOGUID NOT NULL NUMBER(15)

NUMCATALOGGUID NOT NULL NUMBER(15)

INTTEXTTYPE NOT NULL NUMBER(38)

VC2TITLE NOT NULL VARCHAR2(60)

VC2AUTHOR VARCHAR2(100)

NUMPREVINFOGUID NUMBER(15)

NUMNEXTINFOGUID NUMBER(15)

NUMORDER NOT NULL NUMBER(15)

……

调整并最终解决问题

检查发现在numcatalogguid字段上并没有索引,该字段具有很好的区分度,考虑在该字段创建索引以消除全表扫描。

【故障树分析法在数据库分析诊断中应用】

观察系统状况,原大量等待消失:

【故障树分析法在数据库分析诊断中应用】

在另外的session里,持续观察的CPU使用情况:

【故障树分析法在数据库分析诊断中应用】

----以上为创建索引之前部分

----以下为创建索引之后部分,CPU使用率恢复正常

【故障树分析法在数据库分析诊断中应用】

至此,此问题得以解决。

性能何以提高

回答这个问题似乎是多余的,我只想重申一点:有效地降低SQL的逻辑读是SQL优化的基本原则之一。下面来比较一下前后两种执行方式的逻辑读取及性能差异。

(1)全表扫描的性能:

【故障树分析法在数据库分析诊断中应用】

(2)使用索引的性能:

【故障树分析法在数据库分析诊断中应用】

consistent gets从3499到89,可以看到性能得到了巨大的提高。

通常,开发人员很少注意SQL代码的效率,他们更着眼于功能的实现。至于性能问题通常被认为是次要的,而且在应用系统开发初期,由于数据库数据量较少,对于查询SQL语句等,不容易体会出各种SQL句法的性能差异。但是一旦这些应用作为生产系统上线运行,随着数据库中数据量的增加,大量并发访问,系统的响应速度可能就会成为系统需要解决的最主要的问题之一。在少量用户下性能可以接受的SQL,可能在大量用户并发的条件下就会成为性能瓶颈。

在我这个案例中,开发人员很难相信仅只一条SQL语句就导致了整个数据库的性能下降。然而事实就是如此,一条低效的SQL语句就可能毁掉你的数据库,所以在系统设计及开发过程中,你必须考虑到诸多细节,严格的测试也是提早发现问题的有效方法。

如果不幸以上环节都被忽略,那么,DBA(也许就是你)就是最后的一环,你必须能够快速地诊断并解决各种复杂问题。

故障树分析法应用的总结

通过以上的故障解决实例我们可以发现,整个故障的解决过程中,故障树的思想是被不自觉地贯穿始终的,那么现在,通过分析归纳和提炼,我将这个分析思路通过故障树的方法展现出来,希望能够对各位读者朋友有所帮助。

达内 java培训机构转载自网络 如有侵权请联系我们感谢您关注,谢谢支持


【免责声明】本文部分系转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,如涉及作品内容、版权和其它问题,请在30日内与我们联系,我们会予以重改或删除相关文章,以保证您的权益!

Java开发高端课程免费试学

大咖讲师+项目实战全面提升你的职场竞争力

  • 海量实战教程
  • 1V1答疑解惑
  • 行业动态分析
  • 大神学习路径图

相关推荐

更多

Java开班时间

收起