分享

Statspack 分析之等待事件

 wghbeyond 2011-03-09


                                  

本文讲述了"等待"在Statspack报告中的意义是什么,以及如何解读它们。

前5个顶级等待事件

Statspack报告的第3部分就是TOP 5 WAIT EVENT,例如:

Top 5 Timed Events
~~~~~~~~~~~~~~~~~~                                                     
Event                                               Waits    Time (s) % Total Ela Time
-------------------------------------------- ------------ ----------- --------
db file sequential read                       220,409,210   1,086,054    47.33
db file scattered read                         73,431,629     409,421    17.84
CPU time                                                      326,514    14.23
buffer busy waits                              36,731,162     136,089     5.93
PX Deq: Execute Reply                           4,254,794     118,725     5.17

*notes:1)Time的单位为s,cs(1s/100),ms(1s/1000),us(1s/1000000)几种
       2)如果statitics=true,则按time排序,否则按waits排序,运行statspack时必须设为true

     Oracle的等待事件是衡量Oracle运行状况的重要依据及指标。
     等待事件的概念是在Oracle7.0.1.2中引入的,大致有100个等待事件。在Oracle 8.0中这个数目增加到了大约150个,在Oracle8i中大约有200个事件,在Oracle9i中大约有360个等待事件。
    主要有两种类别的等待事件,即空闲(idle)等待事件和非空闲(non-idle)等待事件。

      空闲事件指Oracle正等待某种工作,比如用sqlplus登录之后,但没有进一步发出任何命令,此时该session就处于SQL*Net message from/to client等待事件状态,等待用户发出命令,任何的在诊断和优化数据库的时候,我们不用过多注意这部分事件。
      非空闲等待事件专门针对Oracle的活动,指数据库任务或应用运行过程中发生的等待,这些等待事件是我们在调整数据库的时候应该关注与研究的。

常见的空闲事件
~~~~~~~~~~~~
? dispatcher timer
? lock element cleanup
? Null event
? parallel query dequeue wait
? parallel query idle wait - Slaves
? pipe get
? PL/SQL lock timer
? pmon timer- pmon
? rdbms ipc message
? slave wait
? smon timer
? SQL*Net break/reset to client
? SQL*Net message from client
? SQL*Net message to client
? SQL*Net more data to client
? virtual circuit status
? client message

一些常见的非空闲等待事件
~~~~~~~~~~~~~~~~~~~~~
? db file scattered read
? db file sequential read
? buffer busy waits
? free buffer waits
? enqueue
? latch free
? log file parallel write
? log file sync

     当你试图消除系统的瓶颈时,应该首先查看Statspack报告中的"前5个顶级等待事件"部分。报告的这一部分给出了前5个顶级等待事件、等待事件的完整列表和后台等待事件。如果系统的TEMED_STATISTICS初始化参数被设为"真",这些事件是按其等待时间进行排序的。这种排序是较好的排序方式,因为并不是所有的事件都显示等待。如果TIMED_STATISTICS被设为"假",这些事件就按等待数目进行排序。

解决等待事件

下面是导致等待事件的10个最常见原因,以及对事件的解释和可能的解决方案:

      1. DB文件分散读取(db file scattered read)。这种情况通常显示与全表扫描相关的等待。当全表扫描被限制在内存时,它们很少会进入连续的缓冲区内,而是分散于整个缓冲存储器中。如果这个数目很大,就表明该表找不到索引,或者只能找到有限的索引。尽管在特定条件下执行全表扫描可能比索引扫描更有效,但如果出现这种等待时,最好检查一下这些全表扫描是否必要。因为全表扫描被置于LRU(Least RecentlyUsed,最近最少适用)列表的冷端(cold end),所以应尽量存储较小的表,以避免一次又一次地重复读取它们。

    建议程序中尽量避免使用全表扫描的语句,或者可以增大db_file_multiblock_read_count的值,提高全表扫描一次读取数据块的速度,减少磁盘I/O。

       2. DB文件顺序读取。(db file sequential read)这一事件通常显示单个块的读取(如索引读取)。这种等待的数目很多时,可能显示表的连接顺序不佳,或者不加选择地进行索引。对于高级事务处理(high-transaction)、调整良好(welltuned)的系统,这一数值很大是很正常的,但在某些情况下,它可能暗示着系统中存在问题。你应当将这一等待统计量与Statspack报告中的已知问题(如效率较低的SQL)联系起来。

      检查索引扫描,以保证每个扫描都是必要的,并检查多表连接的连接顺序。DB_CACHE_SIZE也是这些等待出现频率的决定因素。有问题的散列区域(Hash-area)连接应当出现在PGA内存中,但它们也会消耗大量内存,从而在顺序读取时导致大量等待。它们也可能以直接路径读/写等待的形式出现。
   
     一般问题出现在读索引上,建议将业务表空间和索引表空间分开存储在不同的物理卷下,以提高磁盘的I/O性能

3. 释放缓冲区(db file parallel write)。这种等待表明系统正在等待内存中的缓冲,因为内存中已经没有可用的缓冲空间了。如果所有SQL都得到了调优,这种等待可能表示你需要增大DB_BUFFER_CACHE。释放缓冲区等待也可能表示不加选择的SQL导致数据溢出了带有索引块的缓冲存储器,没有为等待系统处理的特定语句留有缓冲区。这种情况通常表示正在执行相当多数量的DML(插入/更新/删除),并且数据库书写器(DBWR)写的速度不够快,缓冲存储器可能充满了相同缓冲器的多个版本,从而导致效率非常低。为了解决这个问题,可能需要考虑增加检查点、利用更多的DBWR进程,或者增加物理磁盘的数量。

     建议增大初始化参数中的db_writer_processes的值

4. 缓冲区忙。这是为了等待一个以非共享方式使用的缓冲区,或者正在被读入缓冲存储器的缓冲区。缓冲区忙等待不应大于百分之一。检查缓冲等待统计部分(或V$WAITSTAT),看一下等待是否位于字段头部。如果事实如此,应增加自由列表(freelist)的组数,或者增加pctused到pctfree之间的距离。如果这一等待处于回退段(undo)头部块,可以通过增加回滚段(rollback segment)来解决缓冲区的问题;如果等待处于回退段(undo)非头部块上,就需要降低驱动一致读取的表中的数据密度,或者增大DB_CACHE_SIZE;如果等待处于数据块,可以将数据移到另一数据块以避开这个"热"数据块、增加表中的自由列表或使用本地化管理的表空间(Locally Managed Tablespaces);如果等待处于索引块,应该重建索引、分割索引或使用反向键索引。为了防止与数据块相关的缓冲忙等待,也可以使用较小的块:在这种情况下,单个块中的记录就较少,所以这个块就不是那么"繁忙"。在执行DML(插入/更新/删除)时,Oracle数据库书写器就向块中写入信息,包括所有对块状态"感兴趣"的用户(感兴趣的事务表,ITL)。为了减少这一区域的等待,可以增加initrans,这样会在块中创建空间,从而使你能够使用多个ITL槽你也可以增加该块所在表中的pctfree(当根据指定的initrans建立的槽数量不足时,这样可以使ITL信息数量达到maxtrans指定的数量)。


5.log file sync
说明任何时候一个事物提交时,它将通知LGWR将LOG_BUFFER写入日志文件,如果此部分占用时间较长,应减少COMMIT的次数,建议将重做日志放到较快的磁盘上进行存储。

6.log file parallel write
等待事件,和上面一样建议将重做日志放到较快的磁盘上进行存储。

5. latch释放。latch是一种低级排队机制(它们被准确地称为相互排斥机制),用于保护系统全局区域(SGA)中共享内存结构。latch就像是一种快速地被获取和释放的内存锁。latch用于防止共享内存结构被多个用户同时访问。如果latch不可用,就会记录latch释放失败。大多数latch问题都与以下操作相关:不能使用邦定变量(库缓存latch)、重复生成问题(重复分配latch)、缓冲存储器竞争问题(缓冲器存储LRU链),以及缓冲存储器中的"热"块(缓冲存储器链)。也有一些latch等待与bug(程序错误)有关,如果怀疑是这种情况,可以检查MetaLink上的bug报告(oracle.com/support)。当latch不命中率大于0.5%时,就应当研究这一问题。在我的下一个Oracle杂志专栏中,将详细介绍latch等待,这一主题本身就需要一整篇文章来介绍。

6. Enqueue。enqueue是一种保护共享资源的锁定机制。该锁定机制保护共享资源,如记录中的数据,以避免两个人在同一时间更新同一数据。

         enqueue包括一个排队机制,即FIFO(先进先出)排队机制。注意:Oracle的latch机制不是FIFO。Enqueue等待通常指的是ST enqueue、HWenqueue、TX4 enqueue和TM enqueue。ST enqueue用于空间管理和字典管理的表空间的分配。利用LMT,或者试图对区域进行预分配,或者至少使下一个区域大于有问题的字典管理的表空间。HW enqueue与段的高水位标记一起使用;手动分配区域可以避免这一等待。TX4是最常见的enqueue等待。TX4 enqueue等待通常是以下三个问题之一产生的结果。第一个问题是唯一索引中的重复索引,你需要执行提交(commit)/回滚(rollback)操作来释放enqueue。第二个问题是对同一位图索引段的多次更新。因为单个位图段可能包含多个行地址(rowid),所以当多个用户试图更新同一段时,你需要执行提交或回滚操作,以释放enqueue。第三个问题,也是最可能发生的问题是多个用户同时更新同一个块。如果没有自由的ITL槽,就会发生块级锁定。通过增大initrans和/或maxtrans以允许使用多个ITL槽,或者增大表上的pctfree值,就可以很轻松地避免这种情况。最后,TM enqueue在DML期间产生,以避免对受影响的对象使用DDL。如果有外来关键字,一定要对它们进行索引,以避免这种常见的锁定问题。

7. 日志缓冲空间。当你将日志缓冲(log buffer)写入重做日志(redo log)的速度比LGWR的写入速度快,或者是当日志转换(log switch)太慢时,就会发生这种等待。为解决这个问题,可以增大日志文件的大小,或者增加日志缓冲器的大小,或者使用写入速度更快的磁盘。你甚至可以考虑使用固态磁盘,因为它们的速度很高。

8. 日志文件转换。所有的提交请求都需要等待"日志文件转换(必要的归档)"或"日志文件转换(chkpt.不完全)"。确保归档磁盘未满,并且速度不太慢。DBWR可能会因为输入/输出(I/O)操作而变得很慢。你可能需要增加更多或更大的重做日志,而且如果DBWR是问题症结所在的话,可能需要增加数据库书写器。

9. 日志文件同步(log file parallel write)。当一个用户提交或回滚数据时,LGWR将会话期的重做由日志缓冲器写入到重做日志中。日志文件同步过程必须等待这一过程成功完成。为了减少这种等待事件,可以尝试提交更多的记录(如一次提交50个记录,而不是一个)。将重做日志置于较快的磁盘上,或者交替使用不同物理磁盘上的重做日志,以降低归档对LGWR的影响。不要使用RAID 5,因为它对于那些书写很多的应用程序速度很慢,可以考虑使用文件系统直接输入/输出,或者使用原始设备(raw device),它们在书写信息时的速度非常快。


10. 空闲事件。在输出之后列出了几个空闲等待事件,你可以忽略它们。空闲事件一般被列在每节的底部,并且包括诸如送给/来自客户机构的SQL*Net消息以及其他与后台相关的时间选择。空闲事件被列于stats$idle_event表中。

11 enq: TM - contention

数据库在执行远程INSERT的时候应用反映很慢,应该是外键约束上没有建立索引的问题。


等待事件快速参考指南

等待问题 可能的解决方法
DB文件分散读取 表明有许多全表扫描:调优代码;存储较小的表。
DB文件顺序读取 表明有许多索引读取:调优代码(特别是连接)。
释放缓冲区 增大DB_CACHE_SIZE;缩短检查点;调优代码。
缓冲区忙 段头部:增加自由列表或自由列表组。
缓冲区忙 数据块:分离"热"数据;利用反向键索引和/或较小的块。
缓冲区忙 数据块:增大initrans和/或maxtrans。
缓冲区忙 回退段头部块:增加回滚段或区域。
缓冲区忙 回退段非头部块:增大提交频率;使用更大的回滚段或区域。
释放latch 详细研究latch。
Enqueue—ST 利用LMT或预分配较大的区域。
Enqueue—HW 对高于最高水位标记的区域进行预分配。
Enqueue—TX4 增大与表或索引相关的initrans和/或maxtrans。
Enqueue—TM 对外来关键字进行索引,检查锁定表的应用程序。
日志缓冲空间 增大日志缓冲;利用较快的磁盘进行重做日志。
日志文件转换 归档磁盘变慢或已满;增加更多或更大的重做日志。
日志文件同步 一次提交更多的记录;利用更快的重做日志磁盘或原始设备。
空闲事件 忽略

常见空闲事件
事件 空闲事件类型
调度程序定时器 共享服务器
锁定管理器等待远程消息 Oracle9i Real Application Clusters
Pipe get 用户处理
Pmon定时器 后台处理
PX 空闲等待 并行查询
PXDeq信用:需要缓冲 并行查询
PX Deq信用:发送blkd 并行查询
rdbms ipc消息 后台处理
Smon定时器 后台处理
来自客户机的SQl*Net消息 用户处理
虚拟电路状态 共享服务器


等待事件相关视图

3.1 v$session_wait
这是一个寻找性能瓶颈的关键视图。它提供了任何情况下session在数据库中当前正在等待什么(如果session当前什么也没在做,则显示它最后的等待事件)。当系统存在性能问题时,本视图可以做为一个起点指明探寻问题的方向。V$SESSION_WAIT中,每一个连接到实例的session都对应一条记录。
V$SESSION_WAIT中的常用列
~~~~~~~~~~~~~~~~~~~~~~~
SID: session标识
EVENT: session当前等待的事件,或者最后一次等待事件。
P1,P2,P3,P1TEXT,P2TEXT,P3TEXT: 等待事件中等待的详细资料
WAIT_TIME: session等待事件的时间(单位,百分之一秒),如果本列为0,说明session当前正在等待,不等于0表示last wait.
STATE:
--Waiting:SESSION正在等待这个事件,此时wait_time = 0,Seconds_in_wait值是实际的等待时间(单位:秒)。
   --Waited unknown time:表示是last wait,且由于设置了timed_statistics值为false,导致不能得到时间信息。表示发生了等待,但时间很短,此时wait_time = -2,seconds_in_wait无用。
--Wait short time:表示是last wait,,但由于时间非常短不超过一个时间单位(1s/100),所以没有记录,此时wait_time = -1,seconds_in_wait无用。
--Waited known time:表示是last wait,如果session等待然后得到了所需资源,那么将从waiting进入本状态,此时wait_time > 0是last wait的时间,而seconds_in_wait表示上一此last wait 开始后到当前的时间间隔,seconds_in_wait - wait_time/100则自然表示last wait end后到当前的时间间隔。
列出系统当前等待事件

列出指定SID的等待事件
~~~~~~~~~~~~~~~~~
SQL> select * from v$session_wait where sid=140;
3.2 v$session_event
本视图记录了每个session的每一项等待事件。由上文所知V$SESSION_WAIT显示了session的当前等待事件,而V$SESSION_EVENT则记录了session自启动起所有的事件。
V$SESSION_EVENT的常用列
~~~~~~~~~~~~~~~~~~~~~~
SID:session标识
EVENT:session等待的事件
TOTAL_WAITS:此session当前事件的总等待数
TIME_WAITED:此session总等待时间(单位,百分之一秒)
AVERAGE_WAIT:此session当前事件平均等待时间(单位,百分之一秒)
TOTAL_TIMEOUTS:等待超时次数

SQL> col WAIT_CLASS for a10
SQL> SELECT sid, seq#, event, wait_class, seconds_in_wait, state
2    FROM (SELECT * FROM v$session_wait ORDER BY seconds_in_wait DESC)
3   WHERE rownum <= 10;

       SID       SEQ# EVENT                          WAIT_CLASS SECONDS_IN_WAIT STATE
---------- ---------- ------------------------------ ---------- --------------- --------------
       223          5 pmon timer                     Idle                119936 WAITING
       216          8 rdbms ipc message              Idle                118990 WAITING
       219          8 rdbms ipc message              Idle                113925 WAITING
       199         10 SQL*Net message from client    Idle                 85074 WAITING
       205        176 SQL*Net message from client    Idle                  6899 WAITING
       220       3782 smon timer                     Idle                  6543 WAITING
       193         40 SQL*Net message from client    Idle                  4534 WAITING
       198        342 SQL*Net message from client    Idle                  3969 WAITING
       200         37 SQL*Net message from client    Idle                  3772 WAITING
       225          9 rdbms ipc message              Idle                  2765 WAITING

10 rows selected

~~~~~~~~~~~~~~~~~
SQL> col event for a50
SQL> select * from (select * from v$session_event order by total_waits desc) where rownum<=10;

       SID EVENT                          TOTAL_WAITS WAIT_CLASS
---------- ------------------------------ ----------- --------------------------
       216 rdbms ipc message                    30599 Idle
       221 rdbms ipc message                    21091 Idle
       221 log file parallel write              11799 System I/O
       224 rdbms ipc message                    10700 Idle
       217 control file sequential read         10330 System I/O
       223 pmon timer                           10328 Idle
       217 control file parallel write          10282 System I/O
       217 rdbms ipc message                    10258 Idle
       222 rdbms ipc message                    10255 Idle
       225 rdbms ipc message                    10226 Idle

10 rows selected

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多