buffer cache与相关的latch等待事件
1.buffer cache
2.latch:cache buffers lru chain
3.latch:cache buffers chains
1.buffer cache
我的理解:
buffer cache理解成4块结构: 三个列表+1个pool
三个列表指:
lru (最近最少使用列表)
dirty list (checkpoing queue)
hast bucket (与latch:cache buffer chain相关)
一个pool指:
buffer pool = db_cache_size / db_block_size
buffer pool:
内存中,数据存放的位置,每个pool的大小就是db_block_size大小.
比如,db_cache_size=800M,db_cache_size=8192,那么,buffer cache中包含的buffer pool 就有102400个(800*1024*1024/8192).
lru:
最近最少使用列表,一个顺序的清单,最上面为:MRU端(最常使用的对象),最下面为:LRU端(最不常用的对象)
在数据库初使化时,所有的buffer都被hash到LRU列表上管理;
当要从数据文件中读取数据时,首先要在LRU列表上查找free buffer,找到后才读取到buffer pool(即buffer cache)中.
dirty list:
脏数据列表,指向内存中需要写入数据文件的buffer pool的地址
hash bucket:
对于buffer pool,如果都通过一种结构管理,像从前面102400个pool中如果要找一个pool的话,性能会很低下.为了提高效率,oracle引入了 bucket结构,oracle将所有的buffer通过hash算法将buffer存放到不同的bucket上,用户需要定位buffer时,只用到 bucket中查找少量的buffer就可以找到.这样就提高了效率.
buffer cache的原理:
这个原理至关重要.
当一个Server进程需要读取数据到buffer cache中时:
1).首先要判断该数据是否存在于buffer中,如果存在,且可用.则获取数据,再根据LRU算法在LRU列表上移动该block;
2).如果数据不存在于buffer中,Server进程就要扫描lru列表,查找可用的buffer空间(free buffer)以放数据到buffer中,
在扫描lru list的过程中,如果碰到已经被修改过的buffer,就将它移动到dirty list(checkpoint queue)上(由于增量检查点的引入,DBWR进程也会主动扫描一定比例的LRU list,将发现的脏数据块移动到dirty lis);
如果dirty list(checkpoint queue)达到了阈值,Server进程就会通知DBWn进程写出脏数据到数据文件(DBWR进程写的一个触发条件);
如果Server进程扫描lru列表到一个阈值还没有找到足够的free buffer,这时,就停止对lru的扫描转而通知DBWR写出脏数据,释放内存空间;这时,进程处于free buffer wait等待.
3).找到足够的buffer之后,Server进程就可以将数据从数据文件读入到buffer cache中;
4).如果读取的block不满足"一致性"需求,则Server进程就需要通过当前block的版本从回滚段中读取该block的"一致性"镜像返回给用户(consistent gets).
2.latch:cache buffers lru chain
当用户读取数据到buffer cache中,或buffer cache根据LRU算法进行管理时,就不可避免的要扫描LRU列表以获取free buffer或更改buffer状态.
buffer cache为众多并发进程提供并发访问,所以在搜索的过程中,必须获取latch锁定内存结构,以防止并发访问对内存中的数据造成损坏.
这个用于锁定LRU的latch就是cache buffers lru chain.
cache buffers lru chain锁存器的默认数量:
DB_WRITER_PROCESSES <= 4 锁存器数= 4 * cpu数
DB_WRITER_PROCESSES > 4 锁存器数= db_writer_processes * cpu数
可以通过初始化参数_db_block_lru_latches来向上调整cache buffers lru chain锁存器的数量(不建议这么做,除非在oracle support的建议下)
如果这个latch竞争激烈:
(1) 适当增大buffer cache,这样可以减少读数据到buffer cache,减少扫描lru列表的次数
(2) 适当增加lru latch数量,修改_db_block_lru_latches参数.不建议这么做.
(3) 使用多缓冲池技术
3.latch:cache buffers chains
引起cache buffers chains争用的原因一:低效率的SQL语句
多个并发低效的SQL语句同时执行,都设法获得相同的数据集,就造成cache buffers chains的争用.
调整高buffer_gets的SQL语句可以缓解这类问题.(较小的逻辑读意味着较少的latch get操作,从而减少锁存器争用并改善性能。)
引起cache buffers chains争用的原因二:热点块(最常见原因)
判断是不是热块问题的常用方法检查latch free事件的p1raw参数值,如果p1raw是相同的锁存器地址,则表明是热块问题.
select sid,event,p1raw,p2,p3,seconds_in_wait,wait_time,state
from v$session_wait
where event = 'latch free';
如果要确定具体的热点块,就要查询v$latch_children,x$bh,dba_extents,根据子latch的信息确认热点块.
v$latch_children.addr 与x$bh.hladdr相关联,可以确认子latch相关的块.
再根据x$bh.dbarfil与dba_extents.relative_fno和x$bh.dbablk与dba_extents.block_id&&block_id+blocks关联,查到具体对象.
1> 查看cache buffers chains子latch情况:
SQL> select * from
(select addr,child#,gets,misses,sleeps,immediate_gets igets,immediate_misses imisses,spin_gets
from v$latch_children
where name = 'cache buffers chains'
order by sleeps desc
)
where rownum<11;
ADDR CHILD# GETS MISSES SLEEPS IGETS IMISSES SPIN_GETS
-------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
69B625BC 739 1056438 65 41 645 0 46
69A821BC 3 1115506 54 39 711 0 34
69B0A9BC 451 1476125 96 30 573 0 83
69A83EFC 9 207227 833 20 800 0 823
69AA573C 119 167852 635 14 592 0 628
69AB2DBC 163 860553 22 14 670 0 15
69B8C19C 876 1283643 1125 12 224 0 1118
69B03E7C 429 315851 53 11 413 0 47
69B1C47C 509 590733 18 11 689 0 14
69BADEBC 987 223777 208 11 529 0 201
2> 联合x$bh视图查出相关块信息
SQL> select b.addr,a.tch,a.ts#,a.dbarfil,a.dbablk,b.gets,b.misses,b.sleeps
from
(select *from
(select addr,ts#,file#,dbarfil,dbablk,tch,hladdr from x$bh order by tch desc)
where rownum<11
) a,
(select addr,gets,misses,sleeps from v$latch_children where name = 'cache buffers chains'
) b
where a.hladdr = b.addr;
ADDR TCH TS# DBARFIL DBABLK GETS MISSES SLEEPS
-------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
69BB451C 17729 6 5 1277992 548061 0 0
69B92CDC 17729 6 5 1277991 581254 0 0
69B7149C 17729 6 5 1277990 534335 0 0
69B4FC5C 17729 6 5 1277989 534914 0 0
69B2E41C 17728 6 5 1277988 1087533 1 0
69B0CBDC 17726 6 5 1277987 538605 0 0
3> 联合dba_extents查出具体的数据对象
select distinct owner,segment_name,segment_type
from dba_extents a,
(select * from (select addr,tch,ts#,file#,dbarfil,dbablk from x$bh order by tch desc)
where rownum<11
) b
where a.relative_fno = b.dbarfil
and a.block_id <= b.dbablk
and a.block_id + blocks > b.dbablk;
4> 联合v$sqltext或v$sqlarea找出相关的SQL语句
select /*+ rule */ hash_value,sql_text
from v$sqltext
where (hash_value,address) in
(select a.hash_value,a.address
from v$sqltext a,
(select distinct a.owner,a.segment_name,a.segment_type
from dba_extents a,
(select dbarfil,dbablk
from (select dbarfil,dbablk
from x$bh
order by tch desc
)
where rownum<11
) b