admin
2010-08-21
<p><strong>How To Identify a Hot Block Within The Database Buffer Cache</strong></p>
<h2>Applies to: </h2>
Oracle Server - Enterprise Edition<br>
Information in this document applies to any platform.<br>
<h2><a name="GOAL" rel="nofollow"></a>Goal</h2>
How to identify blocks which cause latch contention on the 'cache buffers chains' latch.<br>
How to identify a hot block within the database buffer cache.
<h2><a name="FIX" rel="nofollow"></a>Solution</h2>
Possible hot blocks in the buffer cache normally can be identified by a high or <br>
rapid increasing wait count on the CACHE BUFFERS CHAINS latch. <br>
<br>
This latch is acquired when searching for data blocks cached in the buffer cache. <br>
Since the Buffer cache is implemented as a sum of chains of blocks, each of those <br>
chains is protected by a child of this latch when needs to be scanned. Contention <br>
in this latch can be caused by very heavy access to a single block. This can <br>
require the application to be reviewed. <br>
<br>
To solve a hot block, the application maybe need to be reviewed.<br>
<br>
By examining the waits on this latch, information about the segment and the <br>
specific block can be obtained using the following queries.<br>
<br>
First determine which latch id(ADDR) are interesting by examining the number of <br>
sleeps for this latch. The higher the sleep count, the more interesting the <br>
latch id(ADDR) is:<br>
<br>
<div> SQL> select CHILD# "cCHILD"<br>
, ADDR "sADDR"<br>
, GETS "sGETS"<br>
, MISSES "sMISSES"<br>
, SLEEPS "sSLEEPS" <br>
from v$latch_children <br>
where name = 'cache buffers chains' <br>
order by 5, 1, 2, 3; </div>
<br>
Run the above query a few times to to establish the id(ADDR) that has the most <br>
consistent amount of sleeps. Once the id(ADDR) with the highest sleep count is found<br>
then this latch address can be used to get more details about the blocks<br>
currently in the buffer cache protected by this latch. <br>
The query below should be run just after determining the ADDR with <br>
the highest sleep count.<br>
<br>
<div> SQL> column segment_name format a35<br>
select /*+ RULE */<br>
e.owner ||'.'|| e.segment_name segment_name, <br>
e.extent_id extent#, <br>
x.dbablk - e.block_id + 1 block#, <br>
x.tch, <br>
l.child# <br>
from <br>
sys.v$latch_children l, <br>
sys.x$bh x, <br>
sys.dba_extents e <br>
where <br>
x.hladdr = ' &ADDR' and<br>
e.file_id = x.file# and <br>
x.hladdr = l.addr and <br>
x.dbablk between e.block_id and e.block_id + e.blocks -1 <br>
order by x.tch desc ; </div>
<br>
<div>Example of the output :<br>
SEGMENT_NAME EXTENT# BLOCK# TCH CHILD#<br>
-------------------------------- ------------ ------------ ------ ----------<br>
SCOTT.EMP_PK 5 474 17 7,668<br>
SCOTT.EMP 1 449 2 7,668<br>
</div>
<br>
Depending on the TCH column (The number of times the block is hit by a SQL <br>
statement), you can identify a hotblock. The higher the value of the TCH column,<br>
the more frequent the block is accessed by SQL statements.<br>
<br>
In order to reduce contention for this object the following mechanisms can be put in place:<br>
<br>
<blockquote> 1) Examine the application to see if the execution of certain DML and SELECT statements <br>
can be reorganized to eliminate contention on the object.<br>
<br>
2) Decrease the buffer cache -although this may only help in a small amount of cases.<br>
<br>
3) DBWR throughput may have a factor in this as well.<br>
If using multiple DBWR's then increase the number of DBWR's. <br>
<br>
4) Increase the PCTFREE for the table storage parameters via ALTER TABLE <br>
or rebuild. This will result in less rows per block. <br>
<br>
5) Consider implementing reverse key indexes <br>
(if range scans aren't commonly used against the segment) <br>
</blockquote>
Related bugs :<br>
<a href="https://support.oracle.com/CSP/main/article?cmd=show&type=BUG&id=3611471" rel="nofollow">Bug 3611471</a> : High latch waits for "cache buffers chain" latch possible originating from "kcbgtcr: kslbegin .." <br>
<br>
<div>30 min statspack shows <br>
NoWait Waiter<br>
Latch Name Where Misses Sleeps Sleeps<br>
-------------------- -------------------------- ------- ---------- --------<br>
cache buffers chains kcbgtcr: kslbegin excl 0 206,281 280,674</div>
<br>
<a href="https://support.oracle.com/CSP/main/article?cmd=show&type=BUG&id=1967363" rel="nofollow">Bug 1967363</a> "CACHE BUFFERS CHAINS" LATCH CONTENTION AFTER UPGRADE <br>
TO 8.1.7 FROM 8.0.6<br>
<br>
The following query joins with DBA_OBJECTS :<br>
<br>
<div>SQL> with bh_lc as<br>
(select /*+ ORDERED */<br>
lc.addr, lc.child#, lc.gets, lc.misses, lc.immediate_gets, <br>
lc.immediate_misses, lc.spin_gets, lc.sleeps, <br>
bh.hladdr, bh.tch tch, bh.file#, bh.dbablk, bh.class, <br>
bh.state, bh.obj <br>
from <br>
x$kslld ld, <br>
v$session_wait sw, <br>
v$latch_children lc, <br>
x$bh bh <br>
where lc.addr =sw.p1raw <br>
and sw.p2= ld.indx <br>
and ld.kslldnam='cache buffers chains' <br>
and lower(sw.event) like '%latch%' <br>
— and state='WAITING' <br>
and bh.hladdr=lc.addr <br>
) <br>
select bh_lc.hladdr, bh_lc.tch, o.owner, o.object_name, o.object_type, <br>
bh_lc.child#, bh_lc.gets, <br>
bh_lc.misses, bh_lc.immediate_gets, <br>
bh_lc.immediate_misses, spin_gets, sleeps <br>
from <br>
bh_lc, <br>
dba_objects o <br>
where bh_lc.obj = o.object_id(+) <br>
union <br>
select bh_lc.hladdr, bh_lc.tch, o.owner, o.object_name, o.object_type, <br>
bh_lc.child#, bh_lc.gets, bh_lc.misses, bh_lc.immediate_gets, <br>
bh_lc.immediate_misses, spin_gets, sleeps <br>
from <br>
bh_lc, <br>
dba_objects o <br>
where bh_lc.obj = o.data_object_id(+) <br>
order by 1,2 desc; </div>
<p> </p>