Buffer Cache 原理

  • 格式:doc
  • 大小:146.00 KB
  • 文档页数:12

Buffer Cache 原理我们在监控等待事件,查看AWR,ASH报表的时候经常会看到latch: cache buffers chains,有可能还会看到latch: cache buffers lru chain这些等待事件,对于cache buffers chains这个等待事件,相信是大家最为头疼的,如果对Buffer Cache 理解不深,那么你就遇到这些等待事件就会束手无策。

本文的目的就是通过讲解Buffer Cache原理,使大家得心应手的处理这些latch争用。

Buffer Cache概述Buffer Cache是SGA的一部分,Oracle利用Buffer Cache来管理data block,Buffer Cache的最终目的就是尽可能的减少磁盘I/O。

Buffer Cache中主要有3大结构用来管理Buffer Cache。

Hash Bucket & Hash Chain List :Hash Bucket与Hash Chain List用来实现data block的快速定位。

LRU List :挂载有指向具体的free buffer, pinned buffer以及还没有被移动到write list的dirty buffer 等信息。

所谓的free buffer就是指没有包含任何数据的buffer,所谓的pinned buffer,就是指当前正在被访问的buffer。

Write(Dirty)List :挂载有指向具体的dirty block的信息。

所谓的dirty block,就是指在buffer cache中被修改过但是还没有被写入到磁盘的block。

Hash Bucket与Hash Chain ListOracle将buffer cache中所有的buffer通过一个内部的Hash算法运算之后,将这些buffer放到不同的Hash Bucket中。

每一个Hash Bucket中都有一个Hash Chain List,通过这个list,将这个Bucket中的block串联起来。

下面举个简单的例子来介绍一下Hash 算法,Oracle的Hash 算法肯定没这么简单,具体算法只有Oracle公司知道。

•一个简单的mod函数,我们去mod 41 mod 4 = 12 mod 4 = 23 mod4 = 34 mod 4 = 05 mod 4 = 16 mod 4 = 27 mod 4 = 38 mod 4 = 0……………省略…………………..那么这里就相当于创建了4个Hash Bucket如果有如下block:blcok :DBA(1,1) ------> (1+1) mod 4 =2block :DBA(1,2) ------> (1+2) mod 4 =3block :DBA(1,3) ------> (1+3) mod 4 =0block :DBA(1,4) ------> (1+4) mod 4 =1block :DBA(1,5) ------> (1+5) mod 5 =2………........省略…………………....比如我要访问block(1,5),那么我对它进行Hash运算,然后到Hash Bucket 为2的这个Bucket里面去寻找,Hash Bucket 为2的这个Bucket 现在有2个block,这2个block是挂在Hash Chain List上面的Hash Chain List到底是怎么组成的呢?这里我们就要提到x$bh这个基表了SQL> desc x$bhName Null? Type----------------------- - ----------------ADDR RAW(8) ---block在buffer cache中的address INDX NUMBERINST_ID NUMBERHLADDR RAW(8) --latch:cache buffers chains 的addressBLSIZ NUMBERNXT_HASH RAW(8) ---指向同一个Hash Chain List的下一个blockPRV_HASH RAW(8) ---指向同一个Hash Chain List的上一个blockNXT_REPL RAW(8)---指向LRU list中的下一个block PRV_REPL RAW(8)---指向LRU list中的上一个block ………………省略…………………………Hash Chain List就是由x$bh中的NXT_HASH,PRV_HASH 这2个指针构成了一个双向链表,其示意图如下:通过NXT_HASH,PRV_HASH这2个指针,那么在同一个Hash Chain List 的block就串联起来了。

理解了Hash Bucket 和Hash Chain List,我们现在来看看Hash Bucket与Hash Chain List管理Buffer Cache 的结构示意图从图中我们可以看到,一个latch:cache buffers chains(x$bh.hladdr) 可以保护多个Hash Bucket,也就是说,如果我要访问某个block,我首先要获得这个latch,一个Hash Bucket对应一个Hash Chain List,而这个Hash Chain List挂载了一个或者多个Buffer Header。

Hash Bucket的数量受隐含参数_db_block_hash_buckets的影响,Latch:cache buffers chains的数量受隐含参数_db_block_hash_latches的影响该隐含参数可以通过如下查询查看:SQL> select * from v$version;BANNER------------------------------------------------------------------Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64biSQL> SELECT x.ksppinm NAME, y.ksppstvl VALUE, x.ksppdesc describ2 FROM x$ksppi x, x$ksppcv y3 WHERE x.inst_id = USERENV ('Instance')4 AND y.inst_id = USERENV ('Instance')5 AND x.indx = y.indx6 AND x.ksppinm LIKE '%_db_block_hash%'7 /NAME VALUE DESCRIB------------------------- --------------- --------------------------------------_db_block_hash_buckets 524288 Number of database block hash buckets_db_block_hash_latches 16384 Number of database block hash latches_db_block_hash_buckets 该隐含参数在8i以前等于db_block_buffers/4的下一个素数到了8i 该参数等于db_block_buffers*2 ,到了9i 以后,该参数取的是小于且最接近db_block_buffers*2 的一个素数_db_block_hash_latches 该隐含参数表示的是cache buffers chains latch的数量,它怎么计算的我们不用深究可以看到,从8i以后Hash Bucket数量比以前提升了8倍。

可以用下面查询计算cache buffers chains latch的数量SQL> select count(*) from v$latch_children a,v$latchname b where tch#=tch# and ='cache buffers chains';COUNT(*)----------16384还可以用下面查询计算cache buffers chains latch的数量SQL> select count(distinct hladdr) from x$bh ;COUNT(DISTINCTHLADDR)---------------------16384根据我们的查询,那么一个cache buffers chains latch 平均下来要管理32个Hash Bucket,那么现在我们随意的找一个latch,来验证一下前面提到的结构图。

SQL> select * from (select hladdr,count(*) from x$bh group by hladdr) where rownum<=5;HLADDR COUNT(*)---------------- ----------C000000469F08828 15C000000469F088F0 14C000000469F089B8 15C000000469F08A80 24C000000469F08B48 17我们查询latch address 为C000000469F08828 所保护的data blockSQL> select hladdr,obj,dbarfil,dbablk, nxt_hash,prv_hash from x$bh where hladdr='C000000469F08828' order by obj;HLADDR OBJ DBARFIL DBABLK NXT_HASH PRV_HASH---------------- ---------- ---------- ---------- ---------------- ----------------C000000469F08828 2 388 322034 C0000004686ECBD0 C00000017EF8D658C000000469F08828 2 388 396246 C0000004686ECA60 C0000004686ECA60C000000469F08828 18 411 674831 C0000004686ECC00 C0000004686ECC00C000000469F08828 216 411 438948 C0000004686ECBB0 C0000004686ECBB0C000000469F08828 216 220 100217 C0000004686ECAA0 C0000004686ECAA0C000000469F08828 216 220 60942 C000000151FB5DD8 C0000004686ECBD0C000000469F08828 569 411 67655 C00000011FF81668 C0000001E8FB7AC0C000000469F08828 569 280 1294 C0000004686ECB60 C000000177F9F078C000000469F08828 58744570 210 332639 C000000177F9F078 C0000004686ECB60C000000469F08828 65178270 254 408901 C0000004686ECBF0 C0000004686ECBF0C000000469F08828 65347592 84 615093 C0000004686ECB90 C0000004686ECB90C000000469F08828 65349200 765 1259399 C0000004686ECA70 C0000004686ECA70请观察DBA(388,396246),它的NXT_HASH与PRV_HASH相同,也就是说DBA(388,396246)挂载在只包含有1个data block的Hash Chain上。