lru oracle,Oracle buffer cache理解之五——LRU链表结构概述!

在前面的文章中,简单的介绍了oracle是如何在hash链表中搜索需要的数据块以及buffer header的过程,这里我们简单说明一下,如果没有在hash链表上找到所要的buffer header时,oracle会发生IO,到磁盘中去读取数据块,然后拷贝一份到buffer cache中的内存数据块里,后面具体的实现,是否有空闲cache,这里就不说明了,详细请看前面一篇文章。当然这里就要深入LRU和LRUW等链表结构了。

通过前面的文章,我们知道LRU链表是用来查找可重用的内存数据块块的,这里我们来看一下oracle是如何使用LRU链表的,以下已11G为准。

LRU链表和LRUW链表具有两个子链表,叫辅助链表和主链表,另外还针对buffer header增加了一个属性:touch数量(每个buffer header曾经被访问过的次数,用来对LRU链表进行管理),buffer header每访问一次,touch数量就会增加1,可以通过touch数量来反应某个内存数据块总共被访问的次数,但这是并不是精确的。

下面举一个简单的例子:假设buffer cache中只能容纳4个数据块,同时只有一个hash chain和一对LRU,当读入一个数据块时,该数据块对应的buffer header会挂到LRU辅助链表的最末端,同时touch数量+1,读取第二个不同的数据开时,第二块数据块对应的buffer header会挂到前一个buffer header的后面,从而第二块数据块位于LRU辅助链表的最末端,同时touch+1,以此类推,4个数据块全部用完以后的LRU链表可以用下图描述,每个buffer header的touch数量都为1.

LRU辅助链表:

BH1 touch:1(尾端)BH2 touch:1BH3 touch:1BH4 touch:1(首端)

此时主LRU链表是空的。BH1对应第一个查询数据块的buffer header,BH2对应第二个查询数据块的buffer header,BH3对应第三个查询数据块的buffer header,BH4对应第四个查询数据块的buffer header

由于LRU辅助链表只能容纳4个数据块,如果此时要求返回第5个数据块,这时oracle发现buffer cache里已经没有空闲的内存数据块了,于是就会从LRU辅助链表的尾端开始扫描,这里也就是从BH1处开始扫描,查找可以被代替的数据块,扫描的规则和可被代替数据块的规则如下:

1)如果被扫描到的buffer header的touch数量小于隐藏参数_db_aging_hot_criteria(该参数缺省为2)的值,则选中该buffer header作为牺牲者,并立即返回该buffer header所含有的数据块的地址。

2)如果当前buffer header的touch数量大于_db_aging_hot_criteria的值,则不会使用该buffer header。但是如果当前的_db_aging_stay_count的值小于_db_aging_hot_criteria的值,则会将当前该buffer header的touch值赋值给_db_aging_stay_count;否则将当前buffer header的touch数量减掉一半。

oracle总是从尾端开始扫描,那这里的BH1的touch数量为1,此时BH1会作为第一个牺牲者,对应的内存数据块的内容会被清空,同时将第5个数据块的内容拷贝进去,接下来发出第6个和第7个sql,第6个sql要求返回第5个数据块,第7个sql要求返回第4个数据块,也就是当前链表中的BH1和BH4,因为这2个数据块都在LRU辅助链表上,oracle会增加BH1和BH4的touch数量,同时将该BH1和BH4从LRU辅助链表上摘下,转移到LRU主链表的中间位置,我们用图下描述一下现在的LRU链表结构。

LRU辅助链表:BH1和BH4已经被摘下,BH2和BH3变成尾端和首端

BH2 touch1(尾端)BH3 touch:1(首端)

LRU主链表:

BH1 touch:2(尾端)BH4 touch:2(首端)

此时BH1对应第6个查询数据块的buffer header(同时也是第5个查询数据块的),BH2对应第二个查询数据块的buffer header,BH3对应第三个查询数据块的buffer header,BH4对应第7个查询数据块的buffer header,

如果此时又执行了第8句sql,要求返回第三个查询的数据块,也就是当前链表中的BH3,这时BH3会插入到LRU主链表上的BH1和BH4中间,并将BH3从LRU辅助链表摘下,这里要注意的是,每次向LRU主链表插入buffer header的时候,都是从中间插入。如果发来第9个sql,要求返回BH2,同样BH2会移入到LRU主链表的中间,此时主链表满了,LRU辅助链表空了,没有buffer header。

如果此时发来看第十句sql,要求返回一个全新的数据块,oracle就会先扫描LRU辅助链表,但上面没有任何buffer header,然后会扫描LRU主链表,从尾部开始扫描,采用前面所说的牺牲规则来挑选牺牲者,挑出的可以被替代的buffer header将从LRU主链表摘下,放入LRU辅助链表中。

如上就是oracle管理LRU链表的方式,可以从管理方式中看出,oracle总是希望保留多次被访问的数据块在内存中,同时又考虑到了有限的内存资源,这样达到了一箭双雕的效果。

转载请注明: 版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!

最后编辑:2014-01-09作者:Jerry

61f384f23c24a3306817dc87a6906c2d.png

一个积极向上的小青年,热衷于分享--Focus on DB,BI,ETL

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值