Buffer busy waits

 

from:http://blog.csdn.net/tianlesoftware/article/details/5807800

 

一.等待事件的相关知识:

 

1.1 等待事件主要可以分为两类,即空闲(IDLE)等待事件非空闲(NON-IDLE)等待事件

1). 空闲等待事件ORACLE正等待某种工作,在诊断和优化数据库的时候,不用过多注意这部分事件。

2). 非空闲等待事件专门针对ORACLE的活动,指数据库任务或应用运行过程中发生的等待,这些等待事件是在调整数据库的时候需要关注与研究的。

 

 

在Oracle 10g中的等待事件有872个,11g中等待事件1116个。 我们可以通过v$event_name 视图来查看等待事件的相关信息。

 

1.2 查看v$event_name视图的字段结构:

SQL> desc v$event_name;

 名称                   是否为空? 类型

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

 EVENT#                NUMBER

 EVENT_ID              NUMBER

 NAME                 VARCHAR2(64)

 PARAMETER1          VARCHAR2(64)

 PARAMETER2          VARCHAR2(64)

 PARAMETER3          VARCHAR2(64)

 WAIT_CLASS_ID        NUMBER

 WAIT_CLASS#          NUMBER

 WAIT_CLASS           VARCHAR2(64)

 

1.3 查看等待事件总数:

SQL> select count(*) from v$event_name;

  COUNT(*)

----------

      1116

 

 

1.4 查看等待事件分类情况:

/* Formatted on 2010/8/11 16:08:55 (QP5 v5.115.810.9015) */

  SELECT   wait_class#,

           wait_class_id,

           wait_class,

           COUNT( * )AS"count"

    FROM   v$event_name

GROUPBY   wait_class#, wait_class_id, wait_class

ORDERBY   wait_class#;

 

WAIT_CLASS# WAIT_CLASS_ID WAIT_CLASS                count

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

          0    1893977003 Other                       717

          1    4217450380 Application                  17

          2    3290255840 Configuration                24

          3    4166625743 Administrative               54

          4    3875070507 Concurrency                  32

          5    3386400367 Commit                        2

          6    2723168908 Idle                         94

          7    2000153315 Network                      35

          8    1740759767 User I/O                     45

          9    4108307767 System I/O                   30

         10    2396326234 Scheduler                     7

         11    3871361733 Cluster                      50

         12     644977587 Queueing                      9

 

1.5 相关的几个视图:

V$SESSION 代表数据库活动的开始,视为源起。

V$SESSION_WAIT  视图用以实时记录活动SESSION的等待情况,是当前信息。

V$SESSION_WAIT_HISTORY  是对V$SESSION_WAIT的简单增强,记录活动SESSION的最近10次等待。

V$SQLTEXT  当数据库出现瓶颈时,通常可以从V$SESSION_WAIT找到那些正在等待资源的SESSION,通过SESSION的SID,联合V$SESSION和V$SQLTEXT视图就可以捕获这些SESSION正在执行的SQL语句。

V$ACTIVE_SESSION_HISTORY: 是ASH的核心,用以记录活动SESSION的历史等待信息,每秒采样一次,这部分内容记录在内存中,期望值是记录一个小时的内容。

WRH#_ACTIVE_SESSION_HISTORY : 是V$ACTIVE_SESSION_HISTORY在AWR的存储地。

V$ACTIVE_SESSION_HISTORY: 中的信息会被定期(每小时一次)的刷新到负载库中,并缺省保留一个星期用于分析。

DBA_HIST_ACTIVE_SESS_HISTORY: 视图是WRH#_ACTIVE_SESSION_HISTORY视图和其他几个视图的联合展现,通常通过这个视图进行历史数据的访问。

V$SYSTEM_EVENT 由于V$SESSION记录的是动态信息,和SESSION的生命周期相关,而并不记录历史信息,所以ORACLE提供视图V$SYSTEM_EVENT来记录数据库自启动以来所有等待事件的汇总信息。通过这个视图,用户可以迅速获得数据库运行的总体概况。

 

 

 

二.常见的等待事件

 

      Buffer busy waits

从本质上讲,这个等待事件的产生仅说明了一个会话在等待一个Buffer(数据块),但是导致这个现象的原因却有很多种。常见的两种是:

当一个会话视图修改一个数据块,但这个数据块正在被另一个会话修改时。

当一个会话需要读取一个数据块,但这个数据块正在被另一个会话读取到内存中时。

 

Oracle 操作的最小单位是块(Block),即使你要修改一条记录,也需要对这条记录所在的这个数据块做操作。 当你对这个数据块做修改时,其他的会话将被阻止对这个数据块上的数据做修改(即使其他用户修改的不是当前用户修改的数据),但是可以以一致性的方式读取这个数据块(from undo)。当前的用户修改完这个数据块后,将会立即释放掉加在这个数据块上的排他锁,这样另一个会话就可以继续修改它。 修改操作是一个非常短暂的时间,这种加锁的机制我们叫Latch。

 

当一个会话修改一个数据块时,是按照以下步骤来完成的:

以排他的方式获得这个数据块(Latch)

修改这个数据块。

释放Latch。

 

Buffer busy waits等待事件常见于数据库中存在的热快的时候,当多个用户频繁地读取或者修改同样的数据块时,这个等待事件就会产生。 如果等待的时间很长,我们在AWR或者statspack 报告中就可以看到。

 

这个等待事件有三个参数。 查看有几个参数我们可以用以下SQL:

    SQL> select name, parameter1, parameter2, parameter3 from v$event_name where name='buffer busy waits';

NAME         PARAMETER1  PARAMETER2  PARAMETER3

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

buffer busy waits    file#      block#     class#

 

   在下面的示例中,查询的方法和这个一样,所以其他事件对参数的查询将不做过多的说明。

 

File#: 等待访问数据块所在的文件id号。

Blocks 等待访问的数据块号。

ID 在10g之前,这个值表示一个等待时间的原因,10g之后则表示等待事件的类别。

 

from :http://www.dba-oracle.com/art_builder_bbw.htm

One of the most confounding problems with Oracle is the resolution of buffer busy wait events. Buffer busy waits are common in an I/O-bound Oracle system, as evidenced by any system with read (sequential/scattered) waits in the top-five waits in the Oracle STATSPACK report, like this:

Top 5 Timed Events
                                                          % Total
 Event                         Waits        Time (s)     Ela Time
 --------------------------- ------------ ----------- -----------
 db file sequential read       2,598        7,146           48.54
 db file scattered read       25,519        3,246           22.04

 library cache load lock         673        1,363            9.26
 CPU time                      2,154          934            7.83
 log file parallel write      19,157          837            5.68

The main way to reduce buffer busy waits is to reduce the total I/O on the system. This can be done by tuning the SQL to access rows with fewer block reads (i.e., by adding indexes). Even if we have a huge db_cache_size , we may still see buffer busy waits, and increasing the buffer size won't help.

The resolution of a "buffer busy wait "  events is one of the most confounding problems with Oracle.  In an I/O-bound Oracle system, buffer busy waits are common, as evidenced by any system with read (sequential/scattered) waits in the top-five waits.

Reducing buffer busy waits reduces the total I/O on the system. This can be accomplished by tuning the SQL to access rows with fewer block reads by adding indexes, adjusting the database writer or adding freelists to tables and indexes.  Even if there is a huge db_cache_size , the DBA may still see buffer busy waits and, in this case, increasing the buffer size will not help.

The most common remedies for high buffer busy waits include database writer (DBWR) contention tuning, adding freelists to a table and index, implementing Automatic Segment Storage Management (ASSM, a.k.a bitmap freelists), and, of course, and adding a missing index to reduce buffer touches.

In order to look at system-wide wait events, we can query the v$system_event performance view. This view, shown below, provides the name of the wait event, the total number of waits and timeouts, the total time waited, and the average wait time per event.

select *
from
   v$system_event
where
   event like ‘%wait%’;
 
EVENT                       TOTAL_WAITS TOTAL_TIMEOUTS TIME_WAITED AVERAGE_WAIT
--------------------------- ----------- -------------- ----------- ------------
buffer busy waits                636528           1557      549700   .863591232
write complete waits               1193              0       14799   12.4048617
free buffer waits                  1601              0         622   .388507183
 
 
 
 

 
The type of buffer that causes the wait can be queried using the v$waitstat view. This view lists the waits per buffer type for buffer busy waits, where COUNT is the sum of all waits for the class of block, and TIME is the sum of all wait times for that class:
select * from v$waitstat;

CLASS                   COUNT       TIME
 ------------------ ---------- ----------
 data block            1961113    1870278
 segment header          34535     159082
 undo header            233632      86239
 undo block               1886       1706


Buffer busy waits occur when an Oracle session needs to access a block in the buffer cache, but cannot because the buffer copy of the data block is locked. This buffer busy wait condition can happen for either of the following reasons:
  • The block is being read into the buffer by another session, so the waiting session must wait for the block read to complete.  
  • Another session has the buffer block locked in a mode that is incompatible with the waiting session's request.

Because buffer busy waits are due to contention between particular blocks, there's nothing you can do until you know which blocks are in conflict and why the conflicts are occurring. Tuning therefore involves identifying and eliminating the cause of the block contention.

The v$session_wait performance view, shown below, can give some insight into what is being waited for and why the wait is occurring.

 
SQL> desc v$session_wait
 
 Name                                      Null?    Type
 ----------------------------------------- -------- ------------
 SID                                                NUMBER
 SEQ#                                               NUMBER
 EVENT                                              VARCHAR2(64)
 P1TEXT                                             VARCHAR2(64)
 P1                                                 NUMBER
 P1RAW                                              RAW(4)
 P2TEXT                                             VARCHAR2(64)
 P2                                                 NUMBER
 P2RAW                                              RAW(4)
 P3TEXT                                             VARCHAR2(64)
 P3                                                 NUMBER
 P3RAW                                              RAW(4)
 WAIT_TIME                                          NUMBER
 SECONDS_IN_WAIT                                    NUMBER
 STATE                                              VARCHAR2(19)


The columns of the v$session_wait view that are of particular interest for a buffer busy wait event are:

  • P1 —The absolute file number for the data file involved in the wait.  
  • P2 —The block number within the data file referenced in P1 that is being waited upon.  
  • P3 —The reason code describing why the wait is occurring.


Here's an Oracle data dictionary query for these values:

select
   p1 "File #".
   p2 "Block #",
   p3 "Reason Code"
from
   v$session_wait
where
   event = 'buffer busy waits';

If the output from repeatedly running the above query shows that a block or range of blocks is experiencing waits, the following query should show the name and type of the segment:

select 
   owner,
   segment_name,
   segment_type
from 
   dba_extents
where 
   file_id = &P1
and 
  &P2 between block_id and block_id + blocks -1;

Once the segment is identified, the v$segment_statistics performance view facilitates real-time monitoring of segment-level statistics. This enables a DBA to identify performance problems associated with individual tables or indexes, as shown below.

select
   object_name,
   statistic_name,
   value
from
   V$SEGMENT_STATISTICS
where
   object_name = 'SOURCE$';
 
 
 
OBJECT_NAME   STATISTIC_NAME               VALUE
-----------  -------------------------     ----------
SOURCE$       logical reads                     11216
SOURCE$       buffer busy waits                   210
SOURCE$       db block changes                     32
SOURCE$       physical reads                    10365
SOURCE$       physical writes                       0
SOURCE$       physical reads direct                 0
SOURCE$       physical writes direct                0
SOURCE$       ITL waits                             0
SOURCE$       row lock waits



We can also query the dba_data_files to determine the file_name for the file involved in the wait by using the P1 value from v$session_wait for the file_id.

 
SQL> desc dba_data_files
 
 Name                                      Null?    Type
 ----------------------------------------- -------- -----------
 FILE_NAME                                          VARCHAR2(513)
 FILE_ID                                            NUMBER
 TABLESPACE_NAME                                    VARCHAR2(30)
 BYTES                                              NUMBER
 BLOCKS                                             NUMBER
 STATUS                                             VARCHAR2(9)
 RELATIVE_FNO                                       NUMBER
 AUTOEXTENSIBLE                                     VARCHAR2(3)
 MAXBYTES                                           NUMBER
 MAXBLOCKS                                          NUMBER
 INCREMENT_BY                                       NUMBER
 USER_BYTES                                         NUMBER
 USER_BLOCKS                                        NUMBER


Interrogating the P3 (reason code) value from v$session_wait for a buffer busy wait event will tell us why the session is waiting. The reason codes range from 0 to 300 and can be decoded.
 

Code Reason for wait
-A modification is happening on a SCUR or XCUR buffer but has not yet completed.
0The block is being read into the buffer cache.
100We want to NEW the block, but the block is currently being read by another session (most likely for undo).
110We want the CURRENT block either shared or exclusive but the block is being read into cache by another session, so we have to wait until its read( ) is completed.
120We want to get the block in current mode, but someone else is currently reading it into the cache. Wait for the user to complete the read. This occurs during buffer lookup.
130Block is being read by another session, and no other suitable block image was found, so we wait until the read is completed. This may also occur after a buffer cache assumed deadlock. The kernel can't get a buffer in a certain amount of time and assumes a deadlock. Therefore it will read the CR version of the block.
200We want to NEW the block, but someone else is using the current copy, so we have to wait for that user to finish.
210The session wants the block in SCUR or XCUR mode. If this is a buffer exchange or the session is in discrete TX mode, the session waits for the first time and the second time escalates the block as a deadlock, so does not show up as waiting very long. In this case, the statistic: "exchange deadlocks" is incremented, and we yield the CPU for the "buffer deadlock" wait event.
220During buffer lookup for a CURRENT copy of a buffer, we have found the buffer but someone holds it in an incompatible mode, so we have to wait.
230Trying to get a buffer in CR/CRX mode, but a modification has started on the buffer that has not yet been completed.
231CR/CRX scan found the CURRENT block, but a modification has started on the buffer that has not yet been completed .

Reason codes

As I mentioned at the beginning of this article, buffer busy waits are prevalent in I/O-bound systems. I/O contention, resulting in waits for data blocks, is often due to numerous sessions repeatedly reading the same blocks, as when many sessions scan the same index.

In this scenario, session one scans the blocks in the buffer cache quickly, but then a block has to be read from disk. While session one awaits the disk read to complete, other sessions scanning the same index soon catch up to session one and want the same block currently being read from disk. This is where the buffer busy wait occurs—waiting for the buffer blocks that are being read from disk.

The following rules of thumb may be useful for resolving each of the noted contention situations:
 

  • Data block contention —Identify and eliminate HOT blocks from the application via changing PCTFREE and or PCTUSED values to reduce the number of rows per data block. Check for repeatedly scanned indexes. Since each transaction updating a block requires a transaction entry, increase the INITRANS value.  
  • Freelist block contention —Increase the FREELISTS value. Also, when using Parallel Server, be certain that each instance has its own FREELIST GROUPs.  
  • Segment header contention —Again, increase the number of FREELISTs and use FREELIST GROUPs, which can make a difference even within a single instance.  
  • Undo header contention —Increase the number of rollback segments.

Mark Bobak notes that buffer busy waits with P3=0 indicate disk I/O contention, indicating the freelists will not improve concurrency:

"buffer busy wait w/ P3=0 means the buffer is locked because the contents are being read from disk by another session. (See MetaLink Doc ID 34405.1 for more details.)

This is most likely caused by multiple, concurrent sessions that are reading the same table or set of tables. In my experience, it's most often due to multiple, concurrent queries doing full table scans on the same table.

Since this a read concurrency problem, changing freelists will NOT help."

 In these cases, buffering-up the tables (e.g. KEEP pool), or using faster storage (SSD) can remove this disk enqueue wait evsnts.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值