oracle undo 复杂度--oracle核心技术读书笔记四

        一. 概述缓存

        undo 保存的是旧数据。好比,你修改了一条记录将A列abc修改成def,那么undo里面保存的就是abc。目的有两个:1. 若是你的事务没有提交,可是已经将A列修改,那么别人读取这条数据的时候,不该该可以看到你修改后的内容def,应该还只能看到abc,这个时候就须要去读取undo,才能取到abc。 2. 若是你的事务后来失败,须要将A列由修改过的值def回退到以前的值abc,abc也要从undo里面去取。这篇文章,简要介绍一下读一致性(也就是别人没法读取到你修改的未提交的内容)与回滚(事务失败,回滚修改记录)是怎么实现的。oracle


        二. 读一致性spa

        假如会话1 9:00开启事务,9:02分会话2修改了一条数据由A修改成了B,接着9:03分会话2又将同一条数据由B修改成C,会话2尚未提交。会话1   9:04分读取这条数据,应该读取到的是A,可是缓存中这条数据已经被修改为C了,那么怎么取到A呢。oracle是这样处理,在缓存中找到这条数据,发现这条数据被另外的会话修改了,并且另一个会话尚未提交,查看修改时间发现是9:03分,比我会话开启时间9:00要晚,因而在数据块的事务槽中找到 另一个会话这条修改对应的undo记录,这个时候会读取undo块,若是undo已经被刷新输出到磁盘,还须要从磁盘中从新读取出来。这个时候找到的是9:03修改对应的undo块,找到的旧数据是B,若是这条undo记录是9:00以前,咱们就不须要往前找了,可是咱们发现是9:03,咱们还须要找找这条undo前面是否还有undo(自己undo记录会记录上一个undo记录的地址),咱们能找到9:02分那条undo记录。接着再往前找发现没有了,那么9:02分那条undo记录里面的旧数据A就是咱们要找的数据了。听起来好绕,给个图:指针

       

       三.  回滚blog

        回滚就是,事务失败了,咱们须要将这个事务所作的修改所有回退。 说读一致性的时候,咱们主要关注的是找数据所在的单个块,而后找这个块全部的undo记录的一个指针链表。从块开始,一直日后找,直到定位到一个足够老的undo数据。那么回滚其实也相似,回滚说的就是事务的历史,咱们须要事务中全部的undo记录反向排序的指针链表,从最后作的修改开始回退,一直回退到事务作的第一个修改。排序

        回滚和读一致性看起来差很少,其实有一个重要的不一样之处,读一致性,咱们是在内存中生成一个数据块的拷贝,应用undo记录到该拷贝块上,一旦完成相关操做,拿到了旧数据,就会迅速舍弃这个块拷贝,由于咱们的目的是拿到旧数据,并非真的要改变数据。回滚就不一样,回滚是要拿到当前真正的数据块,并应用undo记录来还原。事务

        1. 回滚操做的是当前数据块,undo应用于当前数据块,最终所作的修改是要持久化到磁盘的。而读一致性是不须要的。内存

         2. 回滚操做的是当前数据块,因此当咱们改变它的时候(回滚就是改变),会生成重作(redo),至于会不会生成undo这个没有验证。im

         3. 回滚操做不只跟读一致性同样可能须要从磁盘读取undo数据,还有可能须要从磁盘读取修改的数据,由于修改的数据若是已经被刷新输出到磁盘,还须要从新从磁盘调出来,而后将其值回退到旧值。若是事务比较长,到最后事务失败,那代价是很是大的,回退须要消耗的时间,跟正常事务的时候差很少,甚至更多。链表