Oracle Buffer Busy Wait Event
#LR14217
The buffer busy wait event happens
when a session tries to access a block in the buffer cache but it can't because
the buffer is busy, because another session is modifying the block and the
contents of the block are in flux. To guarantee that the reader has a coherent
image of the block with either all of the changes or none of the changes, the
session modifying the block marks the block header with a flag letting other
users know a change is taking place and to wait until the complete change is
applied.
What
causes the buffer busy wait event
The two main cases where the buffer
busy wait occurs are:
- Another session is reading the block into the buffer -
this specific case has been split out into a separate read by other
session wait event in 10g and higher.
- Another session holds the buffer in an incompatible
mode to our request.
While the block is being changed,
the block is marked as unreadable by others. The changes that are being made
should last under a few hundredths of a second, for example, a disk read should
be under 20 milliseconds and a block modification should be under one
millisecond. Therefore it will take a lot of buffer busy waits to cause a
problem, but some examples of this are:
- Hot block issue, such as the first block on the free
list of a table, with high concurrent inserts. All users will insert into
that block at the same time, until it fills up, then users start inserting
into the next free block on the list, and so on.
- Multiple users running an inefficient SQL statement
performing a full table scan on the same large table at the same time. One
user will read the block off disk, and the other users will wait on buffer
busy waits (or read by other session in 10g and higher) for the physical
I/O to complete.
Getting
more information about buffer busy waits
To get more information about the
SQL statement being executed and the block being waited for, trace the session
or gather data from V$SESSION V$SESSION_WAIT (or just V$SESSION in 10g and
higher):
SELECT
s.sql_hash_value, sw.p1 file#, sw.p2 block#, sw.p3 reason
FROM
v$session_wait sw, v$session s
WHERE
sw.event = 'buffer busy waits'
AND
sw.sid = s.sid
- P1 - file number of the data file containing the block
being waited for
- P2 - block number of the block being waited for
- P3 - this wait is called from many different sections
of Oracle code and each uses their own reason code which differ among
versions
To determine the object being waited
for, use the P1 (file_number) and P2 (block_number) information from the above
query:
SELECT owner , segment_name , segment_type
FROM dba_extents
WHERE file_id = &FileNumber
AND &BlockNumber BETWEEN block_id AND
block_id + blocks -1;
Another query that can be very
useful is finding the objects in the entire Oracle database that are suffering
from "buffer busy waits". The following query gives the top 10
segments:
SELECT
* FROM (
SELECT owner, object_name, subobject_name,
object_type,
tablespace_name, value
FROM v$segment_statistics
WHERE statistic_name='buffer busy waits'
ORDER BY value DESC)
WHERE
ROWNUM <=10
Fixing
buffer busy waits
Once the database object is known,
consider the following causes of contention and their solutions.
- Undo Header
- If using Automatic Undo Management (AUM), increase the size of the undo
tablespace. If not using AUM, add more rollback segments.
- Undo Block
- If using AUM, increase size of the undo tablespace. If not using AUM,
increase rollback segment sizes.
- Data Block-
Data blocks are the blocks that hold the row data in a table or index. The
typical problem is that multiple sessions are requesting a block that is
either not in cache or in an incompatible mode (read by other session in
10g and higher).
- 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.
- Resolve Hot Blocks - If the queries above consistently return the same
block or set of blocks, this is considered a hot block scenario. Delete
some of the hot rows and insert them back into the table. Most of the
time, the rows will be placed in a different block. The DBA may need to
adjust PCTFREE and/or PCTUSED to ensure the rows are placed into a
different block. Also talk with the developers to understand why a set of
blocks are hot.
- Place Table in Memory - 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.
- Fix Low Cardinality Indexes - 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.
- Data Segment Header-
Each segment has one header block that contains segment information, e.g.
free and available block details and the highwater mark. At times, this
block can be a point of contention when multiple sessions are attempting
to insert/delete into/from the same table.
- Adjust PCTFREE/PCTUSED or use ASSM - 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.
- Increase Extent Size - If extents are too small, Oracle must constantly
allocate new extents causing contention in the extent map