statspack系列3
原文:http://jonathanlewis.wordpress.com/2006/12/27/analysing-statspack-3/
作者:Jonathan Lewis
下面的例子中的结果并非从statspack中得出,但是却给我们了一个重要的提醒,statpack如何通过平均来隐藏一些信息而蒙蔽大家的双眼。下面的内容来自于‘Ask Tom’上面的一个帖子:
我的应用是三层架构,使用Oracle 8i作为持久化数据库,从应用的日志中查看,几乎每天都会有超时的问题,整个系统大部分时间也非常慢。我从v$system_event字典表中得到以下信息:
Thu Dec 14 System-wide Wait Analysis for current wait events Event Total Total Name Waits Timeouts ------------------------------ ----------- ----------- null event 1 1 latch free 13,484 13,478 pmon timer 273,516 272,088 rdbms ipc reply 4,390 0 rdbms ipc message 1,421,940 1,145,272 enqueue 4,302 6 reliable message 1 0 control file sequential read 176,526 0 control file parallel write 324,022 0 refresh controlfile command 17 0 local write wait 558 0 buffer busy waits 32,807 4 log file sequential read 56,750 0 log file single write 8,384 0 log file parallel write 148,912 0 LGWR wait for redo copy 59 7 log buffer space 70,206 1 log file switch (checkpoint in 1,071 545 complete) switch logfile command 1,410 0 log file switch completion 3,097 443 log file sync 59,280 64 db file sequential read 6,830,195 0 db file scattered read 9,829,549 0 db file parallel write 7,847 0 direct path read 7,408,664 0 direct path write 2,619,359 0 direct path read (lob) 4,030,001 0 direct path write (lob) 1,275 0 instance state change 1 0 smon timer 2,739 2,732 library cache pin 3 0 file identify 21,002 0 file open 167,006 0 virtual circuit status 27,313 27,313 dispatcher timer 13,661 13,661 SQL*Net message to client 82,049,522 0 SQL*Net more data to client 28,064,378 0 SQL*Net message from client 82,049,497 0 SQL*Net more data from client 6,594 0 SQL*Net break/reset to client 52,752 0
当然这部分不像statspack,也没有时间信息,但是它确实包含了许多经常使用的信息。所以在这些指标中,隐藏了什么信息,你能够提出一些什么问题?
首先,从smon timer可以看出数据库运行了不到10天(smon是每五分钟计时,pmon是每三秒钟),所以无论业务上有任何的高峰,系统的统计数据都很难反映出来。
系统大部分时间都很慢:
从数据反映出来,有上百万的连续,分散,直接读,明显应该是I/O的问题,当然,这是一个10天的汇总数据,总量为24million的物理读请求,平均下来,一天是2.4M,一小时是100,000, 一秒钟是30次,这样下来,数据并非特别大。即使所有的工作都在8小时内完成,那也仅仅才90次/s,所以我们需要更细粒度的数据。
同时,有82million的sql*net的网络“roundtrips”, 太多的round-trips会产生“sql*net more data to client”的非idle等待事件,客户端和网络都看起来非常的繁忙。计算一下每秒钟的活动,大约100个round-trips(如果是8小时的工作日,每秒就是300次),我们是否可以推断:这次更加值得怀疑,除非我们不知道系统当前有多少的并发会话,或许是一个3000 session的系统,真正的问题是cpu。但是当想确认是否是应用程序设计的问题时,我们需要一个更细粒度的数据。
接着,有关lobs的,数据显示有大量的“direct path read(lob)”。几乎一半的直接读都是lobs。这说明lob的数据没有被缓存。似乎缓存这些lob数据来减少I/O能够提高一些性能,但是前提是我们必须弄清,I/O到底是不是问题,当缓存了这部分数据后有没有负面的影响,又会带来有多大的收益,看起来这些问题都需要再斟酌。
大量超时问题
一些小数据,比如相对少量的时间丢失(没有被记录的),很可能就是问题的原因。这些超时可能会告诉我们系统为什么这么慢。4000 enqueues,平均下来400个/天,假设在工作日时间也就是50个/h,也就是大部分持续都不超过3s。或许两秒钟的阻塞会使应用超时,我们看到会有一个enqueue等待一分钟的情况,同样,我们不知道系统有多少个并发sessions,这些等待又是怎么被占用的。
系统有1,701个“logfile switch(checkpoint incomplete)”的等待,当这些等待发生时,用户不能再更新数据库,这一点似乎可以解释应用超时的情况。奇怪的是,在10天里边,有1,410个“logfile switch command”等待,这也意味着每隔10分钟就有在做“alter system switch logfile”操作。
事实上是,有人认为‘busy night time,quiet day time’, 而使用dbms_job来设定了日志文件切换,以便在晚上做处理时有大的日志文件使用。这事从其他的系统中抄过来的吗?还是一个标准设置,还是说白天系统仅有少量的更新。
除此之外,日志相关的数据还有一些奇怪的地方,我们没有看到任何的data block writes。当前已经显示大量的日志文件活动(系统肯定产生了许多日志文件,或者说不太可能有checkpoint incomplete,和log buffer space的等待,除非日志buffer和日志文件都非常的小-所以最好是检查一下基本的配置)。
“LGWR wait for redo”也非常异常,这个等待时间很少见,你可以把它跟系统正在做大量的并发的更新联系起来,但是很明显当前的系统并非是这样的,这仅仅是一个小数据,但是可以暗示着cpu的问题。
可能是系统保持着一直更新着少量相同的块,但只是偶然的提交事务(在10天里仅仅只有59,000次commit(log file syncs))-这个可以帮助解释日志的症状和buffer busy wait等待事件;同样,我们必须回到应用程序里来找到灵感,至少需要看看redo的量,而不仅仅是write waits 的次数。
让我们回到lobs,有少量的“direct path write(lobs)”,如果lobs声明是“nocache logging”,你们少量的大lob的插入或者更新都会产生日志buffer活动的高峰,短暂阻塞系统,然而系统整体平均上看起来都很正常。所以确实需要在一个合理的粒度上面确定问题是否跟活动的高峰期有关。
关于lobs,读出数据后的后续做了什么处理。仅仅是在oracle里的pl/sql过程处理,还是在中间层进行处理,这个例子中看wait events 是否完全是浪费时间。
结论
Sql*net的活动可能暗示中间层有一些并非高效的设计,但除此之外,从v$system_events中得到的报告并不能给出一些额外的信息。
这里有两个快速的配置项检查(log file和log buffer 大小)和一个为什么每10分钟有一个log file切换,但是这些看起来都没有办法关联到用户的性能问题。
虽然有简单的方法可以把lobs缓存起来,但是这也意味着需要更改其它部分,所以这种方法还需要仔细评估才可行。
还有其它几种暗示去发掘问题所在,这里花费了我三个小时来写这篇文章,花费5分钟了解这些统计信息来发掘几种可能性—这里没有写下来,原因是1,它可能需要花费更多的时间;2,现实生活中,我可能会通过检查v$sysstat, v$enqueue_stat, v$filestat, v$sql_workarea, v$segstat, v$latch, v$sql 和其它一些但通常是v$sysstat/v$sesstat来排除他们。
非常清楚,你需要一些时间信息来定位为什么系统会这么慢;但是你更要一个比较合适的粒度上的报告,这样的报告,你可以每15分钟从statspack的快照中获取,这样就不会再平均高峰期的数据而隐藏问题所在了,在这个case中,在应用超时的那一个或两个15分钟的快照中可能会得到一些跟oracle表现出来症状一致的有用信息。
然后,单单的看等待次数是不够的,你至少需要知道这些等待事件背后的工作,比如引起redo waits等待的redo的产生量是多少,引起direct path reads等待的活动是什么,所以,你需要能够把等待时间和工作负载结合起来分析。
最终,困难的是,如果没有合理的收集的数据,完整的指标,不同的统计数据之间关联的理解,那么只能达到一连串的“或许”。
当我参与一个性能调优时,我通常都会最终出具一个五个选项的清单,因为那是客户真正想要的。
同时会给他们排个序,“最需要做的”,“或许有帮助的”,“简单,但是可能效果不明显”。同时会给每一个选项一个清晰的投入产出分析。