暂无图片
暂无图片
2
暂无图片
暂无图片
暂无图片

oracle undo原理

运维笔记本 2020-03-10
3081

   Oracle undo的作用主要有两个:第一是回滚事务,第二是产生一致性读。同时也衍生出了一些新的 功能,比如Flashback query。传统的 undo是通过undo segment 来管理的,我们看下面的示例:



    事务开始,必须首先在data block中分配 ITLITL 中记录了事务 ID(XID)XID 由三部分内容组成: XIDUSN(回滚段号) XIDSLOT(回滚段槽号 )XIDSQN( 序列号),在 Undo segment header中有一个事务表,记录该回滚段上的事务信息,每个事务都会占据了一个回滚槽, XID对应一个UBA(undo block address),表示该事务回滚信息的开始位置。 在上面的例子中,事务分别在 T1,T2,T3时间执行了三个操作,更新了三个 block中的数据,在每个data block中都存在一个 ITL,指向undo segment header中的事务表。 undo信息分别存放在三个undo block中, undo信息是一个链表结构,而 undo segment header中的 uba则指向了最后一个undo block,这也是回滚的起始位置。如果事务需要回滚,只需要在 undo segment header中的事务表中找到事务回滚的起始位置,然后通过 undo链表,就可以依次回滚整个事务。

    细心的DBA 一定会发现,在每个 data blockITL 中也有一个 UBA,实际上这个UBA是指向了该 block对应的undo 信息的起始位置,这个 UBA主要的作用是提供一致性读,因为一 致性读需要通过undo信息来构造一个 CR block,通过这个UBA 就可以直接定位到 block的回滚信息的起始位置,而不再需要通过 undo segment header中的事务表。

    在传统的undo 管理模式中, Oracle对于undo data block是一视同仁的,他们都需要首先读入到 data buffer中进行修改,并都会产生 redo信息,修改的过程大致是:产生 undoredo ,更改undo block,产生 dataredo ,修改data block。总之 redo必须要先于数据被记录下来。当数据库发生 crash,可以通过redo 日志,恢复 dataundo block ,然后再通过 undo信息去回滚未提交的事务,保证数据的一致性,所以说 instance recovery的过程是先前滚,再回滚的过程。

    传统的undo 管理有弊端,第一是 undo信息如果不在data buffer中,必须首先从外部文件中读入;第二是 undo的所有变化也必须同时记录 redo,在事务提交时被写入到 redo log中。Oracle 提出了In-Memory UNDO的新特性,将 undo信息都存放在内存结构中,缓解传统 undo管理中带来的开销。

   IMU shared pool中分配一片内存空间(IMU pool),每个新的事务都会分配一个 IMU buffer,它相当于一片事物私有的 undo buffer,用来记录 undo的信息。Data block 中记录了 IMU node的起始位置,通过 IMU buffer中的信息就可以完成一致读,从而大大提升了效率。



   在IMU 模式下, undo信息依然会被写入到redo中,理解这点很重要!因为 Instance recovery需要undo 的信息去回滚未提交的事物,使数据库处于一致状态,如果 redo中没有undo 变化的信息,那么一旦发生 Instance crash,数据库将有可能处于一个不一致的状态。

    事务开始依旧会在data block中的分配 ITL,并且它依然会指向undo segment header的事物表,但是 undo block中的信息并不需要马上写入,这时 undo信息是记录在IMU Buffer中的,这时也不会产生 undo blockredo 信息。在以下两种情况时, undo buffer中的信息会被写入到 undo block中:1.IMU buffer 空间不足; 2.LGWRredo 信息被写入到 redo log中时(比如commit ),在v$sysstat中可以看到 IMU flushIMU commit,分别表示以上两种情况,如果你发现这两个值不断增加,代表系统开启了 IMU特性。

    现在我们已经了解到,IMU中的 undo信息依旧会被写入到redo log中,只不过在 shared pool中分配了一个private undo buffer,一方面可以在内存中完成一致读的操作,另一方面, undo信息只在必要情况下批量写入到 redo log中,保证数据库crash后可以恢复到一致状态。另外, Oracle总是会尽可能的保留undo buffer中的信息,以便可以在内存中完成一致读的操作,而且 undo信息在写入undo block 时,Oracle进行了合并处理,减少了 undo block的消耗量和对应的redo产生量。

    从Oracle 10g 开始,引入了 private redo strands的概念,在shared pool 中分配了一个 private redo buffer的空间,每个事务产生的 redo都放在这里(9i是放在 PGA里面),每个buffer分配一个 redo allocation latch,用来解决9i redo allocation latch的争用问题。其实 IMUprivate redo strands 这个特性是相关的, IMU相当于private undo buffer ,当redo strand或者 undo buffer空间不足时,会发生IMU flash事件,将 redo信息(包括undo )写入到 redo log中。



   IMU实现复杂,在很多情况下 Oracle会自动禁用IMU 特性,比如 RACStream 环境。

(整理自网络)

最后修改时间:2020-03-11 14:05:17
文章转载自运维笔记本,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论