1、概述

Cr块consistent read块也就是用来维护oracle的读一致性的数据块。当查询某些数据的时候,发现数据块的版本比我们要查询的新,例如session1执行了dml操作并没有提交,session2此时查找跟session1相关的dml操作的数据信息,此时查询的数据却是原来的数据信息。

查询的过程会在undo段中查找该数据块的前映像后,然后把前映像和current块合并形成了一个CR block,通过查询cr block就可以满足数据的一致性了。

CR block存在与sga的buffer cache中,在db cache里申请一个数据块,然后对应的回滚段的前映像生成cr block。

cr块的数量是由隐含参数_db_block_max_cr_dba控制的,默认是最高同时存在5个cr块,构造cr块时cr block created计数器都会增加1.

由于cr block和current block的数据块的rdba都是相同的,会放在相同的hash链上,当然某些block的cr block的版本过多,自然会引起hash链上的竞争,导致latch buffer cache chain闩竞争。

当然在利用回滚段的前映像和current block构造cr块时,很有可能回滚段的已经被覆盖,也就会出现常见的ora-01555快照过旧。

一个sql语句如何去查询数据信息了,根据以前的latch基本记载知道获取该数据块的latch然后才能对该数据块进行读取,其实一个sql访问数据信息的数据块,需要像链接一样的结构中去收索这个数据块是否在内存中,此时访问链表也需要一个latch,如果获取失败也就是会产生latch buffer cache chain等待了。

2、一些疑问

问题1:A用户在对block X进行一致性读时构造了cr块,B用户随后也对block X进行一致性读,是直接用A用户构造好的cr块,还是自己再构造一个?

B得到的是A的block X的COPY

我的测试结果很奇怪。

刚开始v$bh里显示是cr块的数量随着一致读的session的增加而增加,但增加到一定数目(我的测试结果是5个)后,一致读的session增加,但cr块不再增加。似乎又开始共享cr块了。(其实原因是这样的:cr数量由隐含参数_db_block_max_cr_dba控制,默认值是5,5个之后开始就覆盖了,否则无限增多,消耗 buffer量太大)

问题2:如果并发一致性读过多,cr块覆盖会不会影响数据读取?也就是说,A1刚构造了cr块,马上就被A2覆盖了,这时A1会怎么读呢?

在宏观领域是并发,在微观领域(buffer级别)都是串行的。 cr构造前还有对  current  block 的访问,对 undo的访问,这两个访问在微观上都是串行的。

以及还有对  cache  buffer chains 的latch竞争。

如果一个 cache  buffer chains下面挂了5个 cr,新的cr又需要产生,肯定是不能覆盖的还没用完的cr block的,一个cr block buffer 在生存周期间肯定有状态位标志正在使用中了,读完才free掉。 如果这种竞争严重,系统中就应该有   buffer  busy  wait 了(当然buffer busy wait 主要是来自另一个场景,就是a进程要读block,cahce中不命中,分配buffer 后读文件,结果由于读文件总是比较慢的,还没读进来这个过程中新的进程也要来读这个block,发现这个block的buffer正被a进程持有,就产生这个事件)。

问题3:如果可以共享的话,其实过程可以类似于读block到buffer,此时可以有一个类似于buffer busy waits的等待,只能有一个进程构造CR,而其他进程等待CR构造完成。如果CR已经构造完成,利用cache buffer chain的读共享新特性,并发性岂不是更高?

cr  block  buffer 具有时效性,当 t1 时间构造的 cr  block  buffer ,在当时的查询 scn 情况下,是有效的。

但是当时间到了 t2 这个点,如果 block 里面本身有了新的事务,查询也有了新的 查询 scn ,你怎么能重用原来的 cr  block  buffer 呢?

cr block  buffer 存在的前提是什么? 是block中存在着比查询scn对应时间点还新的事务,或者还存在没有  cleanout 的 事务,所以oracle需要构造该查询scn所对应的在 该时间点的buffer,该查询所扫描过的buffer必须都使得block中数据具有时间点上的一致性, 所以又叫一致读。这就是  consistent  reads,简称  CR 。

一个  cr  bock  buffer 只对应同一个查询scn。

就假定你的前提: 如果不同时间点的两个查询具有相同的 scn,那实际上第一个查询已经对该block进行了  cleanout的工作,这个block  buffer在被访问到的时候已经不需要通过获取回滚段信息来构造   cr  block 了,还去考虑   cr  block  buffer 太多 需要共享就没价值了。

不同时间点的查询几乎不可能得到相同的查询 scn,所以 cr  block  buffer 不能能确认共享。

关于cr块共享,听起来好像能提高性能,可这只是想当然。

假设process1要对block X进行一致性读,首先要判断是否X已经有cr块存在,如果存在,还要判断该cr块是否符合当前scn的要求。这样有点得不偿失。

而且,对block的变更一般都会很快就commit了,短时间内并发访问不会太多。Oracle的设计师们肯定做过仔细考虑的。

这让我想起了以前的一个问题:Oracle为什么会将尚未commit的数据写入datafile?一般人可能会想(me too):先将数据存放到cache中,等commit时再写入datafile。

实际上事务commit的几率远高于rollback的几率(rollback的代价也远高于commit),直接写入datafile绝对能大幅提高性能。这样想来,会明白Oracle的设计师们的思维果真超群啊!。

问题4:是不是可以猜测到oracle并没有实现cr共享,但又存在需要多个cr的情况,而多个cr可能是同版本的,也可能由于数据修改而不是同版本的?

多个  CR 可能是同版本的情况,查询 scn 是一样嘛? 如果查询 scn 都一样,又存在 CR ,肯定就可以直接读了,还共享啥呢。

 如果不存在 CR ,也不需要从回滚段获取数据,所有事务都是干净的,就直接读了,不需要构造cr。

如果存在CR而查询scn又不一样,那这个问题又分,到底后面这个查询是否需要从回滚段获取数据, 如果不需要从回滚段获得数据,那就不需要构造 CR了。如果需要,如何校验和上一个  CR 实际上是一样的? 看两个查询之间该block是否发生过变化? 很显然这样事情会越来越复杂。所以,我们完全可以理解为,cr是基于scn的查询,不存在什么共享问题。

几个细节:

Cr块不会写入回滚表空间所在的数据文件

cr块是从undo表空间中来的,就会存在一个物理读

http://blog.csdn.net/cymm_liu/article/details/7496775


Oracle中的CR块详解的更多相关文章

  1. oracle中的dual表详解

    oracle中的dual表详解 1.DUAL表的用途 Dual 是 Oracle中的一个实际存在的表,任何用户均可读取,常用在没有目标表的Select语句块中 --查看当前连接用户 SQL> s ...

  2. Oracle中的substr()函数 详解及应用

    注:本文来源于<Oracle中的substr()函数 详解及应用> 1)substr函数格式   (俗称:字符截取函数) 格式1: substr(string string, int a, ...

  3. Oracle中的MD5加密详解

    一.技术点 1. DBMS_OBFUSCATION_TOOLKIT.MD5 DBMS_OBFUSCATION_TOOLKIT.MD5是MD5编码的数据包函数,但偶在使用select DBMS_OBFU ...

  4. oracle中的trim()函数详解

    1.先看一下Oracle TRIM函数的完整语法描述 TRIM([ { { LEADING | TRAILING | BOTH }[ trim_character ]| trim_character} ...

  5. oracle中临时表的用法详解

    转至:https://blog.csdn.net/mystonelxj/article/details/85010856?utm_medium=distribute.pc_relevant.none- ...

  6. Oracle中job的使用详解

    我们在项目开发中,常常会有一些复杂的业务逻辑.使用oracle的存储过程,可以大大减少java程序代码的编写工作量,而且存储过程执行在数据库上,这样可以利用oracle的良好性能支持,极大地提高程序执 ...

  7. 转 java中static{}语句块详解

    原文地址:http://blog.csdn.net/lubiaopan/article/details/4802430     感谢原作者! static{}(即static块),会在类被加载的时候执 ...

  8. java中static{}语句块详解

    static{}(即static块),会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法,下面我们详细的讨论一下该语句块的特性及应用. 一.在程序的一次执行过程中,stati ...

  9. Oracle中instr 函数的详解

    INSTR    (源字符串, 目标字符串, 起始位置, 匹配序号)    在Oracle/PLSQL中,instr函数返回要截取的字符串在源字符串中的位置.只检索一次,就是说从字符的开始    到字 ...

随机推荐

  1. Content-Type一览

    文件扩展名 Content-Type(Mime-Type) 文件扩展名 Content-Type(Mime-Type) .*( 二进制流,不知道下载文件类型) application/octet-st ...

  2. [Android]应用的前后台运行

    在开发中,你是不是没有抽象一个出常用的类,那你可能要为你的懒惰付出很大的代价.要时刻记得自己的工具箱,不断往里面添加一些小小玩意.今天就给大家带来一个很有意思的例子.前后台运行!! 在Android开 ...

  3. [未完成][Mooc]关于IO总结

    整个课程的大纲:1.编码问题.2.File类的使用3.RandomAccessFile的使用4.字节流的使用.5.字符流的使用.6.对象的序列化和反序列化. 视频1:文件的编码Eclipse的一大特点 ...

  4. sqlserver和oracle中对全半角的转换

    oracle中对全半角的转换 to_single_byte(c)转换成半角 to_multi_byte(c)转换成全角 SELECT To_single_byte('881898?71') FROM ...

  5. poj 3159 差分约束

    思路:班长的糖果要比snoopy的多.并且要用手写堆栈,且堆栈的大小要开到20000000. #include<iostream> #include<cstdio> #incl ...

  6. MySQL数据库的存储结构

    --把若干条sql语句封装起来,起个名字,叫做过程,也是没有返回值的函数 --把这个过程存储在数据库中->存储过程 --存储过程的创建过程 create procedure proceduceN ...

  7. AES加密和Base64混合加密

    /// <summary> /// AES加密方法(AES加密和Base64混合加密) /// </summary> /// <param name="toEn ...

  8. Android之View方法

    onFinishInflate() 回调方法,当应用从XML加载该组件并用它构建界面之后调用的方法 onMeasure() 检测View组件及其子组件的大小 onLayout() 当该组件需要分配其子 ...

  9. java实现的身份证照片脸部识别(头像截图) 以及OCR字体识别

    断断续续地折腾了大半个月,终于把身份证照片脸部识别以及OCR字体识别功能用Java实现了,需求很简单:通过摄像头所照的一张放在黑色底板上的身份证照,识别照片上身份证里面的人名和地址(OCR中文),再截 ...

  10. Cocos2d-x中__Array容器以及实例介绍

    __Array类在Cocos2d-x 2.x时代它就是CCArray类.它是模仿Objective-C中的NSArray类而设计的,通过引用计数管理内存.__Array继承于Ref类,因此它所能容纳的 ...