UNDO内存结构剖析

一、场景

     Oracle的 C事物从早上9:00开始读取A表全部10w行数据,这个而读取需要经历5分钟。在9:01的时候,B事物将A表删除100条记录,那么,当9:05的时候,事物C读取完成,能读取到多少条记录?

  其实,按照一致性原则,需要读取10w行记录,而不是9900行。这个,oracle将如何实现呢?

 

二、Undo的内存结构原理

   只要oracle undo空间足够大,undo能保存所有数据库的更改,能使表数据闪回到任意时刻。如何做到这一点,需要从oracle的undo空间结构说起。


 

   数据块S中,保存了上一次事物的XID。能够找到UNDO表空间中的事务表和回滚块。而此时,B事物对数据块S进行修改,然后提交,此次过程中,UNDO表空间结构变成了什么样呢?这个过程中,因为原先事物已经提交,B事物会覆盖数据行的事物信息XID,UNDO空间会为B事物分配新的事物表B和新的回滚块B,undo表空间的链接结构就变成如下图:在上述示例中,假设数据块S是C事物需要读取的数据块。在9:00时,它在UNDO表空间结构,如下:

 

 

   从图中,可以得知,当B事物覆盖了以前的事物槽信息,重新构建了UNDO结构之后,只要事物表A和回滚段A没有被其他事物覆盖,都能在UNDO空间中被找到。而事物表A和回滚段A是否被覆盖,取决于UNDO空间的大小。

三、ORACLE实现准确读的原理

1、9:00,开始读取时,数据库的SCN假设为scn900。

2、9:01,B事物对数据块S进行修改,并提交,数据表A被删除了100条记录,此时,数据块的SCN被更改为scn901.

3、C事物开始读取数据块S,发现SCN为901,说明数据块在C事物开始读之后,被别的事物修改了,此时数据块需要读取它之前的数据,也就是scn号小于scn900的数据。

4、构造cr块。按照上图中,根据数据行,能找到当前的事务表,以及当前的回滚块。而在当前回滚块中,又记录了前一个事物对应的事务表,根据前一个事物表对应的回滚块,oracle能找到小于scn900的数据块,并构造成cr块,读取出来。

    由以上的逻辑,可以看出,在undo表空间中,只要表空间够大,可以由当前事物,找到任何之前的事物所做的修改,并且能还原到这个修改之前的数据状态。这就是为什么能通过as of timestamp sysdate-1/24找到1天之前的数据的原因了。

四、ORA-01555(snap too old

   继续分析以上场景。如果查询时间很长,在查询的过程中,数据块S被修改了10次,而如果undo空间很小,10次中的前两次,在undo空间中的事务表和回滚块都被覆盖了。而按照oracle的规则,查询需要查询到这10次修改之前的数据块,此时,oracle已经无法构造出来了,就出现了经典的ora-01555错误。

   这个错误有两个形成原因:(1)查询时间过长。(2)undo表空间过小。

   如果频繁出现ora-01555的错误,就需要观察UNDO的大小是否合适了。

 

posted on 2016-11-16 14:32  罗武  阅读(937)  评论(0编辑  收藏  举报