http://www.itpub.net/thread-1108225-1-1.html
案例: CPU 100%使用率
好久没有发案例文章了,最近元旦,大家相对比较清闲,客户的问题也不是很复杂,终于能够抽出几个小时来写点技术方面的冬冬鸟……
(由于有些内容比较敏感,我在这里不贴任何真实的查询语句与抓到的数据,听俺描述就好了)
今天我们要讨论的是一个比较有趣(诡异?)的性能问题,在俺每一步的推导之前请大家都停下来思考一下:如果自己的公司出现这个问题的话应当如何处理
:)
因为很多性能问题都类似于这个case,问题的根源往往与现象看起来风马牛不相及,所以在看文章的时候千万不要只是记住了问题与结论,甚至记住每一步推论的步骤都不会为读者在工作时起到任何帮助的,真正有用的内涵可以被概括成两个英文单词,文章最后揭晓答案哦。^_^
让我们开始吧。
客户是一个世界上很有名的公司,他们最近新上了一套系统,为SUNSolaris 8 + DB2 V8 FP15,平时跑起来好好的一点问题没有。可是,他们每周都会或多或少地遇上一两次100%CPU使用率,然后造成系统down,不得不重新启动操作系统。
上面就是这次问题的现象,假设这个问题出在诸位读者的系统里面,大家应当如何入手分析?为什么要那样入手分析?
=================================================
首先自然是抓数据,没有数据的话所有的猜测也就只能称为“猜测”,而不能称为分析……
在什么情况下抓什么数据,这是作为系统管理DBA的问题诊断的第一门课,也是必须要自学的一门课。每个人面对同样问题时需要的数据可能都是不同的,因为每 个人分析问题的思路和切入点都不同,所以没有人能够写出本书来说在hang的时候抓这些这些,在crash的时候抓这些这些……
对于这个问题,诸位都认为应该抓什么数据呢?
=================================================
首先问题的现象就是操作系统CPU高,那么nmon是必须的,换句话说至少要有vmstat,ps-elf。
另一方面是数据库,因为这个系统是完全的数据库系统,那么出问题基本可以认为是数据库问题了,那么从DB2角度来讲,我们需要检测整体情况,还要检测每个 连接。所以也就是至少要有snapshotfor database/applications与db2pd–everything的信息。
那么这些信息该怎么抓?什么时候抓?系统死了以后肯定不能抓了,系统好好跑的时候抓了没用,只能在系统将死的那一段时间的数据才有用,对不?
而且就算只有了当时的一个vmstat又能看出什么?CPU高……高了……高了……然后呢?正常情况下CPU怎么样,CPU增高的速率怎么样?抓信息不能只抓一个时间点,而是要从一段时间出发去理解问题。
那么也就是说,我们不能只抓一次这些数据,而是要不停地抓啊抓啊……那么问题就是,以什么样的速率去抓?
====================================================
这个就是仁者见仁智者见智的问题了,没有标准答案,只要是适合自己的就好……根据这个问题的现象,平时一个小时抓一组数据,当CPU超过某一个正常标准时,应该有一个后台监测程序去一分钟抓一组数据,才能够比较准确地反映出问题。
因此我们可以写一个cronjob平时一个小时抓一组数据,然后还要写一个后台守护进程几秒钟检测一下CPU,如果超出了某一个使用率则调用另一个程序来一分钟抓一次数据……相信这些对诸位能够读到这里还没有睡着的读者来说都不困难。
:)
也许你要问:那你怎么知道超过某个使用率的CPU一定会产生问题呢?说不定就是workload高了,过一会就好了呢……
没错,如果这样的话我们就把这些数据忽略掉不看就好了……反正系统down的时候我们肯定知道,而且我们肯定会在那之前就开始抓数据了,所以我们肯定会抓到问题发生时的数据阿……
======================================================
我们抓了这些信息都要看什么?很多情况下人们抓了无数的信息,然后就不知道该怎么办了。尽管大家都知道问题肯定是能够被这些信息反映出来的,但是面对几百兆甚至几个G的文本文件有点狗咬刺猬无从下口的感觉。
在这个问题中,我们首先要知道,是不是DB2引起的问题。
当我们能够确认是DB2的问题,下一个要问的就是什么东西造成高CPU,如果是DB2进程,那么是某一个进程吃掉了所有的CPU,还是很多小的进程一起吃掉了所有的CPU。
每次问的问题不要太多,让我们先来回答这两个。
从捕捉到的数据来看,问题发生的时候CPU的增长率非常非常快,基本上可以认为是几分钟之内就冲到了100%,而不是像一些其他的case里面,可能用了3,5天的时间才渐渐增高到100%。
这个现象可以说明什么?问题是短时间内产生的,而不是像内存泻露那种需要几个小时到几天才能够有明显症状的问题。
那么下一个问题,我们有没有什么进程消耗了过高的CPU?这个问题怎么看?很多人喜欢看ps aux,实际上在对于warehouse这种系统来说,里面的那个百分比是完全没有用的。
想一想它的运算规则,是CPU运行总时间除以进程运行总时间……
%CPU
(u and vflags) The percentage of time the process has used the CPU since the process started.The value is computed by dividing the time the process uses the CPU by theelapsed time
of theprocess. In a multi-processor environment, the value is further divided by thenumber of available CPUs because several threads in the same process can run ondifferent CPUs at
the sametime. (Because the time base over which this data is computed varies, the sumof all %CPU fields can exceed 100%.)
那么如果这个进程在刚开始的10个小时里面完全不做工,最后的1秒钟内消耗所有的CPU,ps aux所得到的结果也是0%。
:)
所以ps里面的%CPU基本没用。
那么怎么看一个进程的CPU使用率?topas是一个不错的选择,但是只能在问题发生的时候看……
嘿嘿,大家知道么?
=============================================
当然是ps –elf |sort +5 –rn | grep –i “db2” | grep –i “”咯,C列可不是玩具:
C
(-f, l,and -l flags) CPU utilization of process or thread, incremented each time thesystem clock ticks and the process or thread is found to be running. The valueis decayed by the
schedulerby dividing it by 2 once per second. For the sched_other policy, CPUutilization is used in determining process scheduling priority. Large valuesindicate a CPU intensive
processand result in lower process priority whereas small values indicate an I/Ointensive process and result in a more favorable priority.
按照C列降序排列,最高的就是CPU消耗最高的db2进程。
在结果中,我们的确看到了几个进程有着高C,那么下一步就是要验证这些进程到底在干什么。
怎么看?
对比snapshot看咯。既然我们知道了哪几个db2agent消耗了高CPU,那么在application snapshot里面查找对应的
PID,我们看到了大概30多个进程都在运行同样的一个查询语句。语句中包含parametermarker,也就是?
每个语句消耗的CPU时间都不大相同,短的只有几秒钟,长的则有几十秒了。这点是可以理解的,因为不同的parametermarker所包含的参数可能不一样,那么造成消耗不同CPU的结果也可以理解了。
看到这里,我们可以大致的认为这个查询语句是导致高CPU的直接原因(不一定是根本原因),那么下一个我们要问的就是,到底是先有鸡还是先有蛋?
是由于系统的某些问题导致这些查询都变慢了,然后一大堆一起执行造成系统更慢的恶性循环呢;还是说这些查询本来不应该这么多一起跑,但是现在由于什么原因他们一起执行造成了高CPU呢;或者说本来应该一大堆一起跑,但是每一个查询不应该消耗这么多CPU呢?
我们知道找到问题根源的思路肯定就在上面三种可能性的其中一种,那么让我们来一个一个地排除和推导吧……
首先让我们来想想怎样证明或者排除第一种可能性。
怎么看?
从现有的数据我想不出好办法……你们呢?有什么建议?
既然想不出来就不暂时不想,让我们看看第二种可能性。
第二种可能性就要看平时正常的数据了。通过检查平时的数据,我们发现该查询平时基本上不会同时出现4条以上。可是出现问题的时候却达到了30多条……为什么?
这个很有可能是切入的重点哦……因为这个间接地排除了第三种可能性,也就是平时不应该这么一大堆一起跑……
现在我们面前的是两种可能性,要不就是这些查询出于什么原因变慢了,原本单位时间内应该执行少量的查询,现在却需要执行一大堆……或者原本就不应该有那么多查询,但是某一段时间突然来了一堆……
下一步应该干什么?
不知道读者们都会怎么做,反正我是要客户重新抓数据,这一次加大正常时抓数据的密度,做到一分钟一次。
这次的数据发现了点有趣的冬冬。
在问题发生之前的几分钟内,从正常的数据中我们发现了很多该查询出于LockWaiting状态。
这个说明了什么?
估计有人看到这里就该明白了前因后果了……
这是由于某些东西让这个查询造成了
Lock Waiting,然后这些查询都不能执行,然后越来越多的查询进来都被锁住。而后的某一时刻那个锁突然松了,这样所有的查询同时开始执行,造成了对系统十几倍的负担……
下一个问题就是,什么东西锁的呢?
从applicationsnapshot里面,我们发现所有的这些lock实际上都在等同样的一个lock name,然后检查这个lock name所对应的应用程序,发现它在等另外的一个锁……然后再去看那个锁,却发现在applicationsnapshot里面显示这个锁的拥有者是它自 己!
一个应用程序等他自己……可能么?
不可能……难道是
bug?别忙着下结论……
第三次抓数据,这次我们包含进locksnapshot。
从抓到的locksnapshot里面发现了什么呢?这个锁的拥有者的agentid实际上是0!
怎么回事?
如果我们去infocenter查找agent_id_holding_lock就会发现:
If this element is 0 (zero) and the application is waitingfor a lock, this indicates that the lock is held by an indoubt transaction. Youcan use either appl_id_holding_lk or the command line processor LIST INDOUBTTRANSACTIONS command (which displays the application ID of the CICS agent thatwas processing the transaction when it became indoubt) to determine the indoubttransaction, and then either commit it or roll it back.
哈哈,明白发生了什么了么?
问题的根源压根就不再DB2里面,而是负责2-phase commit的应用程序服务器的错误(也不一定是它的错误,至少问题的根源不再DB2里面了)。
这个问题发生的因果关系可以被表达为
indoubt transaction发生-〉锁不能被释放
–〉一个应用程序在等这个锁
–〉使用高CPU的查询在等待这个应用程序正在持有的锁
–〉应用程序不停地发同样的查询
–〉越来越多的查询都在锁等待
–〉应用程序服务器在若干长的时间之后自动解决indbouttransaction(比如回滚)-〉锁释放
–〉很多查询同时得到共享锁,同时执行
–〉造成CPU使用率一下子冲高,系统性能严重下降
–〉新的查询不停地进入
–〉系统越来越慢,恶性循环
–〉系统死掉……
那么怎么解决indoubttransaction呢?那就不是db2的问题咯,把这个问题交给应用程序小组去头疼好了。当然,如果业务允许,把那个查询 改变成UR的isolation level也可以,不过很遗憾对于这个客户的业务不能够使用UR,所以只能从应用程序层搞定了……
嘿嘿,看了这么多的推导如果你还没有睡着,我想应该能发现点东西吧
:)
首先,调优/调错并不是一种根据文档就可以简单完成的任务,而是需要很多的逻辑推导与证明/反证。
简单地说就是如下的循环:
自己提出问题-〉想到应该如何去证明-〉抓数据-〉分析数据-〉提出下一步的问题……
而这个循环也是适用于我自己的,也许其他人可能有不同的思路,不过所有的思路都可以被归纳为两个单词,就是:NarrowDown
只有不停地对问题进行细分,证明或者排除其他的可能性,才能一步一步到达问题的根源,而不是根据现象如同没头苍蝇一样到处乱撞,能不能解决问题全靠运气……
好了,说了这么多,散场了,88
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/21018850/viewspace-1018309/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/21018850/viewspace-1018309/