buffercache实验3-lru和lruw链表(一)

2014-11-24 17:05:00 · 作者: · 浏览: 1

1.Buffer cache中的LRU链表概念:

oracle在hash chain中未搜索到所需要的buffer时,ORACEL 服务进程会发出I/O调用,到磁盘的数据文件中读取相应数据块--除了直接路径读外,此时会将数据块的内容拷贝到buffer cache 内存中--同时会构造一个buffer header。

在将数据块拷贝到buffer cache中时,假如buffer cache是空的,直接拿一个空的内存数据块来用即可。

但是如果buffer cache中的内存数据块全都被用掉了,没有空的内存数据块了,怎么办?这里就用到了LRU链表。

通过LRU 、LRUW等链表来管理哪些块可以被重用(覆盖),以此来加快物理读加载数据块到buffer cache时查找可用内存块的速度。

在前面描述buffer cache结构的图上,也可以看到有两个链表:LRU和LRUW。

在介绍LRU和LRUW前,先说明几个概念。

1. 脏数据块(dirty buffer):buffer cache中的内存数据块的内容与数据文件中的数据块的内容不一致。

2. 可用数据块(free buffer):buffer cache中的内存数据块为空或者其内容与数据文件中的一致。注意,可用数据块不一定是空的。

3. 钉住的数据块(ping buffer):当前正在更新的内存数据块。

4. 数据库写进程(DBWR):这是一个很底层的数据库后台进程。既然是后台进程,就表示该进程是不能被用户调用的。由oracle内置的一些事件根据需要启动该进程,该进程用来将脏数据块写入磁盘上的数据文件。 LRU表示Least Recently Used,也就是指最近最少使用的buffer header链表。LRU链表串连起来的buffer header都指向可用数据块。而LRUW则表示Least Recently Used Write,也叫做dirty list,也就是脏数据块链表,LRUW串起来的都是修改过但是还没有写入数据文件的内存数据块所对应的buffer header。某个buffer header要么挂在LRU上,要么挂在LRUW不能同时挂在这两个链表上。

LRU表示Least Recently Used,也就是指最近最少使用的buffer header链表。LRU链表串连起来的buffer header都指向可用数据块。

而LRUW则表示Least Recently Used Write,也叫做dirty list,也就是脏数据块链表,LRUW串起来的都是修改过但是还没有写入数据文件的内存数据块所对应的buffer header。

某个buffer header要么挂在LRU上,要么挂在LRUW上,不能同时挂在这两个链表上。
#########################################################################################

2.关于X$BH中lru_flag不同标志位的意义
SYS@ bys3>select distinct lru_flag from x$bh; --LRU_FLAG有这5种标记位。
LRU_FLAG
----------
6
2
4
8
0
X$BH.lru_flag 为0,对应在产LRU的冷端头--DSI中有。也可以通过DUMP buffer cache,搜索BH中LRU的值来计算0状态时BH的位置--很复杂啊哈哈。

X$BH.lru_flag 为2,对应:lru-flags: moved_to_tail 在LRU热端

X$BH.lru_flag 为8,对应:lru-flags: hot_buffer 在LRU热端 ---据说还有一种状态是9,也是在热端。

X$BH.lru_flag 为4,对应:lru-flags: on_auxiliary_list

X$BH.lru_flag 为6,对应:lru-flags: moved_to_tail on_auxiliary_list 在辅助LRU

--可以通过查出每种标志位的文件号块号并做DUMP来验证,除了0无法DUMP BH验证,其它都可以。

方法:
SYS@ bys3>select DBARFIL,DBABLK from x$bh where lru_flag=2 and rownum=1;
DBARFIL DBABLK
---------- ----------
2 15796
SYS@ bys3>alter system dump datafile 2 block 15796; --10G不能用这命令,11G可以。

3.LRU链表的管理机制:

8i前的LRU管理机制不再讨论。

8i以后,LRU和LRUW链表都具有两个子链表,分别叫做辅助链表和主链表。

同时对buffer header增加了一个属性:touch数量,也就是每个buffer header曾经被访问过的次数,来对LRU链表进行管理。--x$bh.tch

oracle每访问一次buffer header,就会将该buffer header上的touch数量增加1,因此,touch数量“近似”的体现了某个内存数据块总共被访问的次数。注意,这只是近似,并不精确。因为 touch的增加并没有使用latch来管理并发性。这只是一个大概值,表示趋势的,不用百分百的精确(3秒内的多次对块访问只计一次)。

############################

4.块在LRU上移动时TCH的变化:

1.大表全表扫描只使用辅助LRU,此时TCH=1,如此后再有对大表中某一行的读取,TCH=2。此时如果SMON进程醒来,或者遇到有其它物理读扫描到些块,会将此TCH=2的块移到主LRU热端头,lru_flag=8,TCH清零。

2.正常读取时,在辅助LRU上找到可用块后会将其移动到主LRU的冷端头,lru_flag=0,tch=1
3.主LRU的热端尾的块被挤出到冷端头时,TCH不变。

4.主LRU冷端最尾的块被挤出时,如TCH>=2时,也会被移动到热端头,TCH=0;

5.flush buffer_cache后查询,块都是TCH=0。SMON进程移动主LRU上TCH<2块到辅助LRU上时不清零。

总结下就是:只有移动到热端头时TCH会清零,flush buffer_cache会将所有块的TCH清零.

主LRU与辅助LRU上块的比例大致是:75%,25%。

在数据库刚启动或者刚flush buffer_cache后所有buffer都在辅助LRU上。SMON进程每3秒会从主LRU冷端尾开始扫描,将TCH<2的块移动到辅助LRU,以此维护主LRU与辅助LRU上块的比例。

主LRU上冷端和热端上块的比例是50%,这由隐含参数:_db_percent_hot_default决定的--默认值就是 50

KEEP POOL/RECYCLE POOL里没有冷热端之分。

_db_percent_hot_keep和_db_percent_hot_recycle默认是0,表示数据块进入KEEP POOL/RECYCLE POOL时放在LRU列尾端。

结合后面物理读查找可用buffer 的过程 ,来说明一下LRU与LRUW的原理: 可以参考:

4.物理读的过程,也是在buffer cache中LRU链表上查找挂载可用块的过程,其中也涉及的DBWR写LRUW上脏块的操作,例如:

注:这里的读取是非直接路径读,非大表的全表扫描。关于直接路径读与大表的全扫描,见:

6.如果未查找到所需