buffer cache基本知识点

 

数据结构及Latch

bb



 

Oracle维护1个哈希表,由一系列bucket组成,数据块按照RDBA被映射至相应bucket;同一bucket下的数据块形成一条链表,存放相同RDBA或哈希冲突的数据块;
通过哈希表进程可快速定位一个数据块的位置,其有cache buffer chain latch保护;


数据块在buffer中有其生命周期,oracle采用least-recent-used + touch point算法,故每个数据块都位于LRU或LRUW链表中,为了提高效率每个链表各有一个辅助链表;
一组LRU & LRUW形成一个工作集,由cache buffer LRU chain latch保护;
数据库刚启动或执行flush buffer_cache时,所有内存块都存于LRU-AUX中,初次访问时放入LRU冷端头(全表扫描例外);
块修改后状态变为dirty从而移入LRUW,进而放入LRUW-AUX并写入磁盘;


8i引入增量检查点,相应的新增了CKPTQ(类似的还有FILEQ/OBJQ),脏块按LRBA顺序插入CKPTQ,增量检查点按顺序读取脏块并将其写入磁盘;
相应latch为checkpoint queue latch;


1个工作集包含如下queue

bb


常见问题

1

全表扫描与LRU-AUX
全表扫描的块通常只位于LRU-AUX以便快速重用(除非指定cache选项),因此重复全表扫描某个表可能无法降低物理读;可参照 http://www.laoxiong.net/table_scan_and_buffer_cache.html
oracle尽量按80:20的比例分配LRU/LRU-AUX,由此可能会产生诡异现象,譬如上面链接的最后评论所遇到的问题,vage在http://www.mythdata.com/post/8.html 进行了很好的阐释:
当所有块都在辅助LRU时,Oracle为了急于保证主、辅LRU,块数量80%,20%的比例,第一次查询时,会将大量的块移到主LRU;
刷新buffer_cache后,第一次查询会把大部分块会被放入LRU以满足80:20比例(即便全表扫描也是如此),满足此条件后后续的全表扫描则放入LRU-AUX;
注:11R2算法有所改动,即第一次查询若是全表扫描则buffer块依然留在LRU-AUX中;

 

2
前台进程如何搜索free buffer?
Buffer cache分为多个工作集以round-robin方式存储数据块,前台进程依次访问每个工作集直至获取cache buffer LRU chain latch,若LRU-AUX没有足够空闲块则从LRU冷端头遍历;
若扫描一定的depth仍没有足够空闲块,则通知DBWR写脏块并进行free buffer wait等待;

 

3
块何时进入CKPTQ和LRUW?
变为脏块后进入CKPTQ,需用到checkpoint queue latch;
对于后者,有3种可能
a DBWR每3秒唤醒一次,有两个任务:
1)      检查CKPTQ长度,若恢复时间可能超过fast_start_mttr_target则沿着CKPTQ写脏块
2)      检查LRUW,有脏块即写
b 前台进程扫描LRU时将遇到的脏块放入LRUW
c  前台进程扫描LRU depth时仍未发现可用块,则唤醒DBWR将脏块从CKTPQ移到LRUW,期间进行free buffer waits等待

 


4
如何写脏块?
有两种方式:通过CKPTQ或LRUW,脏块可同时位于CKPTQ和LRUW中;
前者并不改动块在LRU中的位置,写完磁盘后从CKPTQ中移除;
后者先将脏块移入LRUW-AUX进行IO合并,写到磁盘后将其放入LRU-AUX,可立即被重用,故free buffer waits等待时DBWR会从LRUW写脏块;

 

5
如何获取current buffer?
a 找到RDBA对应的bucket,申请cache buffer chain latch遍历其hash chain,跳过RDBA不匹配以及CR buffer
b 定位到CUR buffer,
1)      若请求S而buffer正在以X模式被占用,则加入waiter list释放cbc latch,并进行buffer busy waits等待
2)      请求X而buffer以S模式被占用,则新建1个CUR buffer
不论有没有成功pin住CUR buffer,都要及时释放cache buffer chain latch
c 若此时块不在内存,则以X模式pin住buffer header并释放cbc latch,继而从磁盘读;若此时其他会话访问该块则会进行read by other session等待

 

6
如何判断buffer块位于哪个list?
SQL> select LRU_FLAG,count(*) from x$bh group by LRU_FLAG order by 2;
  LRU_FLAG   COUNT(*)
---------- ----------
         2        768
         4      83190
         6     244729
         0     327358
         8     655972
6/4 –LRU-AUX
0/2—LRU-cold
8/9—LRU-hot
LRU_FLAG为6、4,说明BUffer在辅助LRU中。为0、2,说明在主LRU的冷端,为8、9的,说明在主LRU的热端。

 

参考资料
DSI 405
http://www.mythdata.com/post/8.html

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

转载于:http://blog.itpub.net/15480802/viewspace-1081374/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值