您的位置:首页 > Web前端

揭密buffer Cache中的链表补遗

2014-10-31 11:14 295 查看
揭密buffer Cache中的链表补遗



(揭密Oracle之七种武器之四:揭密Buffer Cache中的链表

http://www.itpub.net/thread-1631537-1-1.html)

补充两个问题:

1、如果一个脏块在CKPT-Q上,当此脏块被移到LRUW时,会从CKPT-Q上去掉吗?

回答:不会。直到从LRUW上被写到磁盘上后,才会从CKPT-Q上去掉。

测试过程很简单,搞一个脏块,然后再运行一个需要大量扫描LRU的操作,我是这样的:

set autot trace

update a2_70m set id2=id2+0 where id1=1;

commit;

select * from a4_70m;

(测试环境和前面所述一致,Buffer Cache 100M,a4_70m 80M,但它被设为了Cache)

然后在另一会话中不停运行如下几条语句:

alter session set events 'immediate trace name SET_TSN_P1 level 5';

set pagesize 50000

set linesize 10000

select file#,dbablk,tch,lru_flag,ba,decode(state,0,'free',1,'xcur',2,'scur',3,'cr', 4,'read',5,'mrec',6,'irec',7,'write',8,'pi', 9,'memory',10,'mwrite',11,'donated'),

decode(bitand(flag,1), 0, 'N', 'Y') dirty,NXT_REPL,PRV_REPL,WA_NXT,WA_PRV,ts#,HLADDR from x$bh a where file#=4 and dbablk=20

order by FILE# , DBABLK;

select CNUM_SET,CNUM_REPL,ANUM_REPL,CNUM_WRITE ,ANUM_WRITE from x$kcbwds where cnum_set>0;

alter session set events 'immediate trace name BUFFER level 0x01000014';

在DUMP结果中,可以找到如下内容:

BH (7c3f497c) file#: 4 rdba: 0x01000014 (4/20) class: 1 ba: 7c298000

……………………(省略部分无意义内容)…………………………………………………………

hash: [8e96e068,8e96e068] lru: [80bf9cc8,7c7efffc]

obj-flags: object_ckpt_list

ckptq: [7bfe8140,7dfea5d0] fileq: [8ea707ec,8ea707ec] objq: [88c3d034,88c3d034]

……………………(省略部分无意义内容)…………………………………………………………

Hex dump of block: st=0, typ_found=1

Dump of memory from 0x7C298000 to 0x7C29A000

……………………(省略部分无意义内容)…………………………………………………………

BH (7c3f497c) file#: 4 rdba: 0x01000014 (4/20) class: 1 ba: 7c298000

……………………(省略部分无意义内容)…………………………………………………………

hash: [8e96e068,8e96e068] lru-write: [8ea63e58,7c7efffc]

obj-flags: object_ckpt_list

ckptq: [7bfe8140,7dfea5d0] fileq: [8ea707ec,8ea707ec] objq: [88c3d034,88c3d034]

……………………(省略部分无意义内容)…………………………………………………………

上一次DUMP的时候,LRU链前后块的指针为lru: [80bf9cc8,7c7efffc],下一次DUMP时,已经变成lru-write: [8ea63e58,7c7efffc],但检查点队列相关的信息没变,都是ckptq: [7bfe8140,7dfea5d0]。

当脏块写完成时,BH中信息变为这样:

BH (7c3f497c) file#: 4 rdba: 0x01000014 (4/20) class: 1 ba: 7c298000

……………………(省略部分无意义内容)…………………………………………………………

hash: [8e96e068,8e96e068] lru: [7c7efffc,7c3f2f18]

lru-flags: on_auxiliary_list

ckptq: [NULL] fileq: [NULL] objq: [88c3d02c,88c3d02c]

……………………(省略部分无意义内容)…………………………………………………………

从lru-write: [8ea63e58,7c7efffc],变为了lru: [7c7efffc,7c3f2f18],从lru-flags可以看到,已经被放到辅助链表中了。同时,ckptq已经是NULL了。写磁盘完成时,才从CKPT-Q上摘掉。

2、根据上面的测试结果,脏块可能会同时存在于两个链表:LRUW和CKPT-Q。块从LRUW写磁盘后,会从CKPT-Q上摘掉。但反过来呢?从CKPT-Q中写磁盘,写完后会从LRUW上摘掉吗?

答案是,会的。

如何验证呢?我是通过Latch的获取来验证的。

脏块通过CKPT-Q写到磁盘后,其所处的LRU位置不变,这一点我在前文中已经提到过,也很容易验证这点,从x$BH中的NXT_REPL,PRV_REPL两列,就可以验证此点。也就是说,从CKPT-Q写脏块,是和LRU链表无关的,也就是不需要获得LRU Latch。如果从CKPT-Q写脏块申请了LRU Latch,哪一定和LRUW有关。

将检查点超时参数设为很小的值,写个简单的DTrace脚本,跟踪一下DBWR进程Latch的获得情况。发现每次从CKPT-Q写脏块时,DBWR都要按如下顺序申请Latch:

获得cache buffers chains Latch

获得LRU Latch

释放LRU Latch

释放cache buffers chains Latch

获得checkpoint queue latch

释放checkpoint queue latch

获得cache buffers lru chain

释放cache buffers lru chain

也就是说,从CKPT-Q写脏块时,不但要获得checkpoint queue latch,还要LRU Latch。根据前面的分析,从CKPT-Q写脏块时,获取LRU Latch的目的,只能是为了访问LRUW,因为CKPT-Q写不改变块在LRU的位置,不必要访问LRU。哪么,CKPT-Q写访问LRUW的目的是什么,可以推论,目的是为了检查脏块是否在LRUW、并摘掉它。

还有一点,由于块已经从LUR移到了LURW,从CKPT-Q写完成后,虽然不是从LURW写的,块应该仍会被放入辅助LRU,这个就是猜想了。我尽量找个测试实际验证下。

([b][b][b][b]块[/b]如果同时处于CKPT-Q和LURW上。[/b]块从CKPT-Q写完成后,就从[b]CKPT-Q[/b]上移除,但还是会在LURW上(在[b]LURW[/b]主链表和辅助连表上有区别吗此时?)的。DBWR搜素[/b][b][b][b]LURW[/b]主链表[/b][/b]时如果发现块是干净块,则会将之放入辅助LRU上??)

[/b]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: