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. s实现指定时间自动跳转到某个页面

    --js实现指定时间自动跳转到某个页面 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &quo ...

  2. eclipse插件svn 提交时报:"svn is already locked"解决方法

    在出错文件夹下,鼠标右键TortoiseSVN->Clean up. SVN错误:Attempted to lock an already-locked dir 1.出现这个问题后使用“清理”功 ...

  3. HBase的JavaAPI操作

    如果是DDL的操作就找HbaseAdmin. 如果是表上的增删改查的操作就找HTable. 附录代码: mport java.util.Arrays; import org.apache.hadoop ...

  4. 网易新闻RSS阅读器

    首先需要分析网易RSS订阅中心的网页布局情况. 网易RSS订阅中心:http://www.163.com/rss/ 你会发现RSS文件由一个<channel>元素及其子元素组成,除了频道本 ...

  5. TSQL基础(四) - 日期处理

    日期类型-DateTime DateTime是sql中最常用的日期类型. 存储大小为:8个字节: 日期范围:1753-01-01到9999-12-31: 精确度:3.33毫秒: 常用的日期函数 Get ...

  6. 学习Learn Python The Hard Way 前言中的一段话,可与君共勉

    在你通过这本书学习编程时,我正在学习弹吉他.我每天至少训练 2 小时,至少花一个小时练习音阶.和声.和琶音,剩下的时间用来学习音乐理论和歌曲演奏以及训练听力等.有时我一天会花 8 个小时来练习,因为我 ...

  7. WCF开发教程资源收集

    WCF开发教程资源收集 1.蒋金楠,网名Artech的博客 [原创]我的WCF之旅(1):创建一个简单的WCF程序[原创]我的WCF之旅(2):Endpoint Overview[原创]我的WCF之旅 ...

  8. Swift字典类

    在Foundation框架中提供一种字典集合,它是由“键-值”对构成的集合.键集合不能重复,值集合没有特殊要求.键和值集合中的元素可以是任何对象,但是不能是nil.Foundation框架字典类也分为 ...

  9. HTML+CSS学习笔记 (7) - CSS样式基本知识

    HTML+CSS学习笔记 (7) - CSS样式基本知识 内联式css样式,直接写在现有的HTML标签中 CSS样式可以写在哪些地方呢?从CSS 样式代码插入的形式来看基本可以分为以下3种:内联式.嵌 ...

  10. Mac OSX用终端检测文件的sha1值

    打开终端,输入shasum空格然后把文件拖进来回车即可;