Monday, July 23, 2012

Is there any way to avoid buffer busy wait?

  • 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 if the block is being read into the buffer by another session, so the waiting session must wait for the block read to complete or another session has the buffer block locked in a mode that is incompatible with the waiting session's request.

  • 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.
  • What's the nature of the queries encountering the buffer busy wait? What kind of segment did you identify? Table? Index? If index, what block? root block? first level branch block?
  • When I see lots of buffer busy waits, I look at the SQL encountering the wait, see if there are opportunities to reduce concurrency, and/or tune the SQL.
  • Cache the table or keep the table in the KEEP POOL.  When multiple sessions are requesting the blocks that reside in the disk, it takes too much time for a session to read it into the buffer cache.  Other session(s) that need the same block will register 'buffer busy wait'.  If the block is already in buffer cache, however, this possibility is eliminated.  Another alternative is to increase the buffer cache size.  A larger buffer cache means less I/O from disk.  This reduces situations where one session is reading a block from the disk subsystem and other sessions are waiting for the block.
  • Look for ways to reduce the number of low cardinality indexes, i.e. an index with a low number of unique values that could result in excessive block reads. This can especially be problematic when concurrent DML operates on table with low cardinality indexes and cause contention on a few index blocks.
  • 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. 
  • Tune inefficient queries that read too many blocks into the buffer cache.  These queries could flush out blocks that may be useful for other sessions in the buffer cache. By tuning queries, the number of blocks that need to be read into the cache is minimized, reducing aging out of the existing "good" blocks in the cache. 
  • The v$session_wait performance view, can give some insight into what is being waited for and why the wait is occurring.

  • When sessions insert/delete rows into/from a block, the block must be taken out of the freelist if the PCTFREE threshold reached.  When sessions delete rows from a block, the block will be put back in the freelist if PCTUSED threshold is reached.  If there are a lot of blocks coming out of the freelist or going into it, all those sessions have to make that update in the freelist map in the segment header.  A solution to this problem is to create multiple freelists.  This will allow different insert streams to use different freelists and thus update different freelist maps.  This reduces contention on the segment header block.  You should also look into optimizing the PCTUSED/PCTFREE parameters so that the blocks don't go in and out of the freelists frequently. Another solution is to use ASSM which avoids the use of freelists all together.
  • If extents are too small, Oracle must constantly allocate new extents causing contention in the extent map

No comments:

Post a Comment