暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

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

何建敏 2016-09-13
357


何剑敏 

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


如何加入"云和恩墨大讲堂"微信群

搜索 盖国强(Eygle) :eyygle,或者扫描下面二维码,备注:云和恩墨大讲堂,即可入群。每周与千人共享免费技术分享,与讲师在线讨论。


近期文章

Linux环境下合理配置大内存页

调整 I/O 相关的等待

oracle 的并行机制

RAC环境下ORA-12545连接错误

认识Oracle 中的 NULL 值

巧用触发器,实现DDL监控

资源下载

(OraNews)回复关键字获取

2016DTCC, 2016数据库大会PPT;

DBALife,"DBA的一天"精品海报大图;

12cArch,“Oracle 12c体系结构”精品海报;

DBA01,《Oracle DBA手记》第一本下载;

YunHe“云和恩墨大讲堂”案例文档下载;


最后修改时间:2020-05-08 00:20:48
文章转载自何建敏,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论