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 我的测试结果很奇怪。 问题2:如果并发一致性读过多,cr块覆盖会不会影响数据读取?也就是说,A1刚构造了cr块,马上就被A2覆盖了,这时A1会怎么读呢? 在宏观领域是并发,在微观领域(buffer级别)都是串行的。 cr构造前还有对 current block 的访问,对 undo的访问,这两个访问在微观上都是串行的。 问题3:如果可以共享的话,其实过程可以类似于读block到buffer,此时可以有一个类似于buffer busy waits的等待,只能有一个进程构造CR,而其他进程等待CR构造完成。如果CR已经构造完成,利用cache buffer chain的读共享新特性,并发性岂不是更高? cr block buffer 具有时效性,当 t1 时间构造的 cr block buffer ,在当时的查询 scn 情况下,是有效的。 一个 cr bock buffer 只对应同一个查询scn。 不同时间点的查询几乎不可能得到相同的查询 scn,所以 cr block buffer 不能能确认共享。 关于cr块共享,听起来好像能提高性能,可这只是想当然。 多个 CR 可能是同版本的情况,查询 scn 是一样嘛? 如果查询 scn 都一样,又存在 CR ,肯定就可以直接读了,还共享啥呢。 如果不存在 CR ,也不需要从回滚段获取数据,所有事务都是干净的,就直接读了,不需要构造cr。 |
|