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. linux云计算集群架构学习笔记:系统文件的目录结构

    文件的基本管理和XFS文件系统备份恢复 1.1  Linux系统目录结构,相对/绝对路径. 1.2  创建/复制/删除文件,rm -rf / 意外事故 1.3 查看文件内容 1.4 xfs文件系统的备 ...

  2. VB.net 字符串 分割 及 重新倒序组装

    ''' <summary> ''' split with ">>>>" , and inverted order ''' </summar ...

  3. [改善Java代码]在switch的default代码块中增加AssertionError错误

    switch的后跟枚举类型,case后列出所有的枚举项,这是一个使用枚举的主流写法,那留着default语句似乎没有任何作用了,程序已经列举出了所有的可能选项,肯定不会执行到default语句,. 错 ...

  4. 【基础数学知识】UVa 11314 - Hardly Hard

    Problem H HARDLY HARD You have been given the task of cutting out a quadrilateral slice of cake out ...

  5. nodejs自己在项目中使用的一个工具库utils.js文件

    文件内容如下: /** * utils.js */ var crypto = require('crypto'); var url = require('url'); var querystring ...

  6. c++ 11 国标标准方面的异常处理与微软在Visual Studio 2012的异常处理的区别

    这段代码: __try { } __except(GetErrorCode()) { } 可以捕获空指针,但是包围在其中的代码不能有自带析构函数的对象.c++ 11 标准里面的auto_ptr关键字, ...

  7. WCF开发教程资源收集

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

  8. 第六十二篇、AFN3.0封装网络请求框架,支持缓存

    1.网络请求 第一种实现方式: 功能:GET POST 请求 缓存逻辑: 1.是否要刷新本地缓存,不需要就直接发起无缓存的网络请求,否则直接读取本地数据 2.需要刷新本地缓存,先读取本地数据,有就返回 ...

  9. (转)推荐一个在Linux/Unix上架设ASP.NET的 WEB服务器--Jexus

    在Linux/Unix上架设ASP.NET WEB服务器,有两个可选方式,一种是Mono+XSP,一种是Mono+Jexus,其它的方式,比如 Apache+mod_mono.Nginx+FastCg ...

  10. easyloader [easyui_1.4.2] 分析源码,妙手偶得之

    用easyui很久了,但是很少去看源码. 有解决不了的问题就去百度... 今日发现,easyui的源码不难懂. 而且结合 easyloader 可以非常方便的逐个研究easyui的组件. 但是, ea ...