oracle 中的CR块详解+

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://llovewxm1314.blog.csdn.net/article/details/7496775

1、概述

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

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

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

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

由于cr blockcurrent block的数据块的rdba都是相同的,会放在相同的hash链上,当然某些blockcr 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://www.itpub.net/thread-1424719-1-1.html

展开阅读全文

Oracle内存中的块过滤情况?

05-23

比如说有两个表A和B 分别有100个块和200个块.rn现在从A表提取符合条件的数据,跟B表符合条件的数据JOINrnrnselect c.name,c.student_id,course_name,scorernfrom rn(rn select student_id,namern from arn where a.name like '张%'rn) crninner joinrn(rnselect b.score,student_id,course_id,course_namernfrom brnwhere insert_time >to_date('2012-03-08','YYYY-MM-DD')rn) drnon c.student_id=d.student_idrnrnA 表符合记录的有10条,并且分布在10个块中.B表符合记录的有30条,分布在20块里. A,B两表无索引rn那么把A表100块和B表200个块扫描到内存SGA里的DATA BUFFER里.rn接着过滤 A表留下了10个块,B表留下20个块在SGA中.rninner JION 操作: 从10块中获取一条记录,去匹配20块中的30条记录. 那么将是10*20=200个块操作.rn最后匹配10行记录,把这10行记录放到回话的PGA里rn在回话的PGA中把不需要的列过滤掉,也就是提取所需要的列,发送到客户端.rnrn如果数据量很大的时候 A表过滤后有1万个块,包含需要1千条记录.B表过滤后有10万个块,包含3千条记录. rn那么这11万个块,很可能无法在SGA的DATABUFFER里放得下,就得放在临时表空间里,放到硬盘上.然后加上JOIN操作 块数. 速度就慢了下来.rnrn 在大数据量情况下 采用物理临时表方法,A表过滤后的1万个块中的1千条记录,写回硬盘,只需要100个块.每个块装10条记录. 那么B表就是300个块.rn 这样就产生400个块IO操作.并且400个块还可能保留在SGA中,接下来的JOIN操作不再需要读IO操作,也不需要那么多块的循环匹配操作.减少了逻辑IO操作!rnrn不知道我这里理解的对不对?rn 论坛

没有更多推荐了,返回首页