lru oracle,ORACLE buffer cache 原理 --LRU链表(参照学习:oracle内核技术揭秘)

OBJ-Q对象列表在合并IO的过程中起了很大作用,因为脏块在从CKPT-Q中移到对象列表的时候会将不同对象的块链在一起,这样更容易找到连续的块进行合并。

LRU链表一共包括4个链表,主LRU、辅助LRU、主LRUW和辅助LRUW,前两者是在buffer cache中寻找可以覆盖的buffer块,后两者也是DBWR用于写脏块的。

物理读时,数据块要写到buffer cache的哪个地方呢?覆盖不常用的buffer ,LRU就登场了,LRU会将所有的buffer都链接在一起,主LRU分为冷端和热端,每个buffer的访问次数都有一个计数器TCH,3秒一个阶段,每阶段只要有进程访问,其值就增加1。

一般辅助LRU占总buffer数的75% ,主LRU辅助LRU主LRUW和辅助LRUW为 一个workset 由buffer cache lru chain latch保护。

物理读的步骤:

1>获取buffer cache lru chain latch的保护

2>先从辅助LRU链表的尾端搜索可以覆盖的buffer(不是脏块,TCH小于2)

3>找到可以覆盖的buffer之后,将其从辅助链表的尾端移到主LRU的冷端头

4>释放buffer cache chain lru  latch

辅助LRU为空的时候 会从主LRU尾去查找buffer,这个过程中如果TCH>2的将会被移到热锻头并且TCH清0,如果有脏块也是不能被覆盖的,会被移到LRUW链表中,被选中的buffer将会被移动到冷端头,并读入数据。

当然辅助LRUW不会一直为空的,SMON进程会每3秒醒来一次,申请获得buffer cache chain lru latch,然后检查主辅LRU的长度,如果辅助LRU小于25%,SMON将会从主LRU的冷端尾搜索TCH<2的费脏块,将其移动到辅助LRU中。

X$kcbwds中可以查看主辅LRU的情况。

大表和小表是由small_table_threshold的隐藏参数控制的,该值默认为buffer cache数的2%

如果是大表,全表扫描oracle会额外处理,物理读的块不会进去主LRU,只会使用辅助LRU的空间,块的TCH=0,11gR2之后,将自动使用直接路径读,不再进入buffer cache。

脏链表LRUW

TCH<2的脏块,这些脏块会被移动到LRUW中,对于比较热的脏块,不急于写。当脏块被移动到LRUW中,并不会马上被写磁盘,DBWR进程会每3秒钟醒来一次,会将脏块移动到辅助LRUW中,从辅助LRUW中写磁盘。这时候就是个有一个脏块就会写,而不是等到一定的数量之后再写。

Buffer  busy wait

前面提到过 buffer busy wait 是服务进程在扫描了40%(受隐含参数db_block_max_scan_pct控制)的LRU之后还没有找到可以覆盖的buffer(被pin住的,脏块。TCH>=2的都不允许被覆盖 ),进程休眠,直到找到可以覆盖的buffer为止。当进入下一流程,会首先判断buffer中的的脏块数,总脏块数超过buffer的25%(这个值由隐含参数db_large_dirty_queue:Number of buffers which force dirty queue to be write控制),将不会等待3秒超时了,而是直接唤醒DBWR写脏块。

DBWR被唤醒后,会首先检查LRUW,如果有脏块,则马上开始写,如果没有脏块,则开始检查检查点队列,判断是否需要从检查点队列写脏块,

从检查点队列写脏块是采用的增量检查点的方式,从LRUW写脏块是采用的,是对增量检查点的一点补充。服务器进程扫描LRU时遇到脏块如果不移动到LRUW,会增加LRU扫描时间,这样会导致LRU latch竞争。

v$sysstat :physical write from cache,DBWR从buffer cache中写入磁盘的脏块,DBWR checkpoint buffer write指的是从检查点队列中写出的所有脏块数,两者意见,就是DBWR从LRUW中写磁盘的脏块数。

脏块一旦进入 LRUW则有以下两种情况,会被写出:

检查点队列中的脏buffer没有达到总buffer数的25%,那么等待3秒超时,DBWR会从LRUW中写脏块。

检查点队列中的脏buffer达到总buffer数的25%,不需要等待超时,服务器进程直接唤醒DBWR,醒来后的DBWR马上会从LRUW中写脏块。

日志切换:

日志切换只是唤醒DBWR 并告知DBWR已经发生了日志切换。日志切换还会触发CKPT进程写数据文件头,当日志文件状态由ACTIVE变为INACTIVE的时候,CKPT才会去写文件头。

日志切换时,CKPT会找到redo file在检查点队列中的RBA最大的脏块,将他的SCN RBA通知DBWR

然后CKPT每3秒醒来的时候,发现redo file的脏块还没有完全写完,再一次醒来,全部写完之后会:修改控制文件中的redo file 的状态,新状态为inactive ,修改控制文件中的SCN,修改数据文件头的SCN和RBA ,总结一下就是,日志切换时,LGWR通知CKPT和DBWR,然后马上开始向下一组redo file中写redo recorder。

切换期间 多有的DML DDL都会被阻塞,进程在等待切换的过程中可能会有 logfile switch 等待。DBWR接到LGWR通知后马上醒来,按正常工作流程工作,CKPT也会马上醒来,检查DBWR的写进制,确定是否现在的current redo file的脏块都写入磁盘了,都写了,会马上修改日志文件状态、数据文件相关状态。日志切换并不是通知DBWR写脏块,而是通知它发生了日志切换,所以DBWR会醒来按原流程写脏块。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值