前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入内核:认识隐含参数_db_block_max_cr_dba

深入内核:认识隐含参数_db_block_max_cr_dba

作者头像
数据和云
发布2018-03-06 16:09:25
7450
发布2018-03-06 16:09:25
举报
文章被收录于专栏:数据和云

何剑敏

Oracle ACS 华南区售后团队,首席技术工程师。多年从事第一线的数据库运维工作,有丰富项目经验、维护经验和调优经验,专注于数据库的整体运维。

_db_block_max_cr_dba 这个隐含参数的作用是控制每个block(即一个dba下,或者说x$bh.dbablk)的最多cr块的个数。默认值是6(5个CR+1个XCUR)。

当产生一致性读(CR)的时候,session会从前镜像读取块,加载到buffer cache中,加载的这个块,我们叫CR copy。保留多个版本的CR,可以缓解对buffer中block的并发争用(buffer busy wait),避免多个session同时读取一个buffer block。但是如果版本过多,挂在一个hash chain下的block太多,又会造成CBC latch的争用。所以oracle选择了6个版本。我们来测试一下CR copy的特性(数据库版本11.2.0.4)

数据初始化

检查初始情况

刚刚启动的时候,我们发现file#=4,block#=1365没有在buffer中。

开始构造一致性读:

session 1

session 2

当开始DML之后,block中数据文件中加载到buffer中,此时一定会有一个xcur的block,和cr block。这是因为DML is always performed on the current copy of the block (Status=xcur).

xcur的block表示当前已经被修改过的block,是最新的block,注意DI列(Dirty列)已经是Y,表示这个block是buffer中的脏块。cr block是在update之前,在内存中copy原来的xcur的block。我们看cr block的CR_SCN_BASE是update前一瞬间的SCN,即2687527。

即当update发生的时候, (1)如果块在buffer中(块的状态为xcur),那么copy一份这个在buffer中的xcur的块,copy出来的块是cr块。更新这个块,且这个块的标记还是xcur。 (2)如果在buffer中没有这个块,那么将这个block从磁盘读到buffer中(此时状态为xcur。这个过程,类似进行了一次没有一致性读的select,select的时候,当前块状态也是为xcur),将buffer中的xcur块,做一份copy,copy出来的块成为cr块,更新这个块,且这个块的状态还是xcur

由于刚刚进行了update,且没有commit。所以现在的select是需要进行一致性读。

session 3:

SQL> select * from t1 where c1=1;

session 2:

第一次的select,oracle一次性创建了2个CR block,分别是在SCN 2687545和SCN 2687546的时候。这个时候,由于是需要一致性读,因此这次的select是从前镜像读取,从undo中读取,所以,也可以看到这个前镜像块是从undo的那个块上读取,可以看到有UBA(undo block address)的file id,block id和sequence。file id为3,是在undo tablespace上。

session 4:

SQL> select * from t1 where c1=1;

session 2:

第二次的select,oracle只创建了1个CR block,分别是在SCN 2687575的时候。 读取的是在undo上的同一个UBA file id,block id和sequence,所以,在undo文件上的块是同一个块,但是在buffer中,cr块目前已经有3个cr块了。另外还有一个cr块,但是这个块是在做update的时候,对于该session来说在update之前的xcur的copy。不是从undo文件中读取的block。

session 5:

SQL> select * from t1 where c1=1;

session 2:

第三次的select,oracle只创建了1个CR block,分别是在SCN 2687595的时候。 读取的是在undo上的同一个UBA file id,block id和sequence,所以,在undo文件上的块是同一个块,但是在buffer中,cr块目前已经有4个cr块了。

另外我们注意到,oracle已经把第一次做update的时候,SCN 2687527的cr块刷出去了。这个被丢弃的CR block,对我做update的session来说,已经没有用处,因为当前session的block的值已经更新,当前session所需要的block是xcur的那个block。而对已其他session来说,由于还没有commit,需要读取前镜像,可以直接做第一次和第二次cr block的copy;或者直接从undo中加载。

session 6:

SQL> select * from t1 where c1=1;

session 2:

第四次的select,oracle只创建了1个CR block,分别是在SCN 2687615的时候。 读取的是在undo上的同一个UBA file id,block id和sequence,所以,在undo文件上的块是同一个块,但是在buffer中,cr块目前已经有5个cr块了。

session 7:

SQL> select * from t1 where c1=1;

session 2:

第五次的select,oracle只创建了1个CR block,分别是在SCN 2687643的时候。 创建这个CR block的时候,把当前cr block列表中最早的SCN 2687545的block丢弃了。只保留5个CR block。

至此,我们看到,不同的session的select,对cr block的影响: update但不commit,在update时产生一个cr block。 第一次select从undo获得前镜像产生2个cr block,当前共3个cr block 第二次select再产生一个cr block,当前共4个cr block 第三次select再产生一个cr block,且丢弃update时的cr block,当前共4个cr block 第四次select再生产一个cr block,至此已经有了5个cr block和1个xcur block 第五次select再产生一个cr block,丢弃第一次select产生的第一个block,只保留5个cr block和1一个xcur block 再后续select的话,每产生一个cr block,丢弃最早的cr block

我们再来看看flush buffer cache的影响: session 2:

session 8:

SQL> select * from t1 where c1=1;

session 2:

我们看到,flush buffer cache之后,xcur的block,即标记为dirty的block也被刷出buffer cache,所有的buffer block都是显示free。

但进行第一次select的时候,被修改的xcur block,还是从db file加载到内存,且被记录成dirty的block。另外,select出来的前镜像,也从undo加载到内存,形成第一个cr block。

到了这个,顺便问个问题,现在都流行database in memory,如果我的内存是256G的,能放得下256G的database吗?读了上面的问题,相信你已经有了初步的答案。:)

---the end

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-09-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据和云 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档