ITPub博客

首页 > 数据库 > Oracle > 深入浅出cache buffer和shared pool记载02

深入浅出cache buffer和shared pool记载02

原创 Oracle 作者:dotaddjj 时间:2011-12-09 16:41:12 0 删除 编辑

当进程需要读取数据到buffer cache或cache buffer根据LRU算法进行管理,就会扫描LRU list获取可用buffer或更改buffer状态,此时在搜索过程中必须获取latch,锁定内存结构(latch是oracle的一种串行锁机制,保护共享内存结构),防止并发访问顺坏内存中的数据。

SQL> col name for a25

SQL> select addr,latch#,name,hash,gets,misses,immediate_gets,immediate_misses from v$latch where name='cache buffers lru chain';

ADDR LATCH# NAME HASH GETS MISSES IMMEDIATE_GETS IMMEDIATE_MISSES

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

03C43568 117 cache buffers lru chain 3559635447 118207 0 31831 0

Cache buffer lru chain latch存在多个子latch,其数量由隐含参数_db_block_lru_latches控制

查找隐含参数的sql

SQL> col ksppdesc for a25

SQL> col ksppstvl for a25

SQL> Select ksppinm name, ksppdesc, ksppstvl

2 from x$ksppi a, x$ksppcv b

3 Where a.indx = b.indx

4 and a.inst_id = userenv('instance')

5 and b.inst_id = userenv('instance')

6 and ksppinm = '_db_block_lru_latches'

7 ;

NAME KSPPDESC KSPPSTVL

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

_db_block_lru_latches number of lru latches 8

以上脚本可以用于查询oracle中所有的隐含参数的脚本,只需要把后面的ksppinm值修改即可!

Select addr,latch#,child#,name,hash,gets,misses,immediate_gets,immediate_misses

from v$latch_children where name='cache buffers lru chain'

ADDR LATCH# CHILD# NAME HASH GETS MISSES IMMEDIATE_GETS IMMEDIATE_MISSES

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

2564E7AC 117 1 cache buffers lru chain 3559635447 12 0 0 0

2564EB5C 117 2 cache buffers lru chain 3559635447 12 0 0 0

------

8 rows selected

如果该latch竞争激烈,通常采取

1 增大buffer cache,增大缓存命中率,减少了LRU list扫描机会

2 增加db_block_lru_latches隐含参数,将产生多个cache buffers lru chain的子latch,减少竞争,不过该隐含_db_block_lru_latches静态参数一般是足够的,建议在oracle support建议或了解深入情况下修改。

3 通过多缓存池技术,db_recycle_cache_size和db_keep_cache_size可以减少不希望的数据老化和全表扫描对于default池的冲击,从而减少竞争!

用户请求查找相应数据会先查看buffer cache中是否存在相应的buffer,那么如何来确认是否存在相应buffer,如果直接遍历buffer cache,那么性能会相当低下!buffer cache的管理还存在hash bucket和cache buffer chain数据结构。

Oracle把管理的所有buffer通过一个内部的hash算法后,存放到不同的hash bucket中,每个hash bucket中都有一个cache buffer chain双向链表将hash bucket内的buffer header信息存储进来,buffer cache通过hash bucket分割之后,众多buffer就被分布到一定数量bucket之中,用户查找数据时只需要先通过hash运算得到相应的hash值然后到相应的hash bucket中查找cache buffer chain的buffer header来确定是否存在!

buffer hash存放的是数据块的概要信息,包括数据块文件号,块地址,状态等,判断数据是否在buffer cache存在,只需要检查buffer header即可确定,buffer header中存在只想具体buffer的指针!

这样如果某个数据块被获取先要获取这个数据块所在的cache buffer chain的latch,如果此时有别的session也在获取该latch,则其他session需要spin,如果spin次数超过_spin_count,也可以休眠sleep下然后再来竞争!

从oracle 9I开始,对于cache buffer chain的只读访问,latch可以被共享,但是如果修改就需要独享这个latch了!(latch由三种内存元素组成:pid(进程ID) 内存地址和内存长度,latch用于保存内存结构的完整性,对对象的访问安全控制是锁lock)

由于buffer根据buffer header进行散列hash运算然后存放于hash bucket,那么hash bucket数量一定程序决定了bucket中buffer多少,相应的hash bucket多点,那么hash

Bucket内的buffer就会少点,那么就能相应的减少cache buffer chain的latch竞争,不过更多的hash bucket则会需要更多的空间于管理成本!

Hash bucket的设置受隐含参数_db_block_hash_buckets的影响,对应每个bucket只存在一个chain,当用户在buffer cache中搜索数据块时,需要搜索相应的bucket的cache buffer chain,此时需要获取cache buffer chain latch,在oracle 8I之前,对于每个hash bucket,oracle使用一个独立的cache buffer hash latch维护,这样_db_block_hash_latches的数量和bucket是一致的。在oracle8I开始,_db_block_hash_buckets数量较以前增加了8倍,而db_block_hash_latchs数量增加有限,由于增加了bucket而减少了每个bucket上的buffer数量,则每个latch可以完全管理多个buckets。

上述的关于db_block_hash_buckets和db_block_hash_latch同样可以用上述的查找隐含参数的脚本查看相应信息!

热点块竞争:很多进程同时对相应的buffer所在的bucket的cache buffer chain访问,将产生cache buffer chain竞争,也就是所谓的热点块竞争!

x$bh数据字典表,也就是存放的buffer headers的信息,buffer header中存储buffer的数据块的文件号 块地址,状态等信息,根据这些信息结合dba_extents视图,可以很容易找到buffer对应的对象信息

其中的tch就是touch缩写,表示一个buffer的访问次数,buffer被访问的次数越多,该buffer所在的bucket内的cache buffer chain竞争越激烈,可能会存在热点块竞争问题。

Addr 地址 TS# 表空间号 file# 数据文件号 dbarfil 文件号 dbablk 数据块号

Tch 访问次数

nxt_hash:cache buffer chain内下一个buffer header编号

Prv_hash:cache buffer chain内下一个buffer header

Nxt_repl:LRU上的下一个buffer

PRV-repl:LRU上的上一个buffer

HLADDR hash chain latch address可以和v$latch_child.addr关联

查询热点块所在的owner和对象 类型

select e.owner,e.segment_name,e.segment_type from dba_extents e,

(select * from (select addr,ts#,file#,dbarfil,dbablk,tch from x$bh order by tch desc)

where rownum<11) b

where e.relative_fno=b.dbarfil and e.block_id<=b.dbablk and e.block_id+e.blocks>b.dbablk

在oracle 10g之前,数据库的等待事件中,所有latch等到被归入latch free等待事件,10g后,有些latch等待可能表现为单独的等待事件。

[@more@]

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/25362835/viewspace-1056772/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
  • 博文量
    220
  • 访问量
    1662980