概述

很多时候我们总会看到CR,但是CR具体是什么?又有什么作用呢?当ORACLE 发生一致性读得时候,会利用UNDO块和当前数据块构造CR块来获得一致性读。但是既然UNDO已经记录了前镜像,为什么还要辛苦的构造CR块呢?直接读取UNDO不就好了吗?下面一起来探讨下CR。

oracle命令详解(中的CR块介绍--一致性读)(1)


CR块

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

oracle命令详解(中的CR块介绍--一致性读)(2)

查询的过程会在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等待了。


构造一致性读,ORACLE需要做的工作

oracle命令详解(中的CR块介绍--一致性读)(3)

1)克隆这个块到另一个buffer,克隆的块跟之前的current块在一个HASH CHAIN上。我们后面的四个步骤,就是发生在新克隆的块上的。

2)如果这个块上存在 延迟块清除或者快速块清除,那么对它进行块清除的动作。

3)对于块上所有未提交的事务进行块级别的回滚,注意这里并不是回滚整个事务,而是只针对事务里修改了这个块的操作进行回滚。

4)检查ITL槽位里,COMMIT SCN有没有大于查询时刻SCN(snapshot SCN)的条目,如果有的话,对这个条目涉及到的事务进行块级别的回滚(类似步骤3)。

5)如果回滚后,ITL槽位里依然有大于查询时刻SCN的条目,重复步骤四。

有几点需要说明:

1)构造一致性读发生在克隆块上,不产生日志。但是在步骤2上,虽然科隆块不产生日志,但是current block由于也需要做块清除,所以会产生日志。

2)步骤四可能会发生多次。如果查询耗时较长,在读取到某个块前,N个事务已经对它做了修改提交,那么这个块就要发生N次步骤4的操作。

3)构造出来的一致性读的块一般由于TCH数很小很容易被LUR算法抛弃重用。

4)一致性读取回滚的只是这个块,假如一个事务修改了1000个块,产生了1000个undo record,但是只有1个undo recored是这个块产生的,那么oracle能够根据ITL槽位里记录的UBA快速的识别到这个undo record,而其他的999条,不会读取。


后面会分享更多devops和DBA方面的内容,感兴趣的朋友可以关注一下~

oracle命令详解(中的CR块介绍--一致性读)(4)

,