oracle redo与undo_笔记2:UPDATE语句
UPDATE
UPDATE所带来的工作与INSERT大体一样。不过UPDATE生成的undo量更大;由于存在UPDATE,所以需要保存一些“前”映像。
块缓冲区缓存中会有更多新的undo段块。为了撤销这个UPDATE,如果必要,已修改的数据库表和索引块也会放在缓存中。下面假设前面的插入语句生成了一些重做日志,其中有些重做日志已经刷新输出到磁盘上,有些还放在缓存中。
假想场景:系统现在崩溃
启动时,Oracle会读取重做日志,发现针对这个事务的一些重做日志条目。给定系统的当前状态,利用重做日志文件中对应插入的redo条目,并利用仍在缓冲区中对应插入的redo信息,Oracle会“前滚”插入。现在有一些undo块(用以撤销插入)、已修改的表块(刚插入后的状态),以及已修改的索引块(刚插入后的状态)。由于系统正在进行崩溃恢复,而且我们的会话不再连接,Oracle发现这个事务从未提交,因此会将其回滚。它取刚刚在缓冲区缓存中前滚得到的undo,并将这些undo应用到数据和索引块,使数据和索引块“恢复”为插入发生前的样子。现在一切都回到从前。
磁盘上的块可能会反映出前面的INSERT,也可能不反映(这取决于在崩溃前是否已经将块刷新输出)。如果磁盘上的块确实反映了插入,而实际上现在插入已经被撤销,当从缓冲区缓存刷新输出块时,数据文件就会反映出插入已撤销。如果磁盘上的块本来就没有反映前面的插入,就不用去管它——这些块以后肯定会被覆盖。
假想场景:应用回滚事务
此时,Oracle会发现这个事务的undo信息可能在缓存的undo段块中(基本上是这样),也可能已经刷新输出到磁盘上。它会把undo信息应用到缓冲区缓存中的数据和索引块上,或者倘若数据和索引块已经不在缓存中,则要从磁盘将数据和索引块读入缓存,再对其应用undo。这些块会恢复为其原来的行值,并刷新输出到数据文件。
这个场景比系统崩溃更常见。需要指出,有一点很有用:回滚过程中从不涉及重做日志。只有恢复和归档时才会读取重做日志。这对于调优是一个很重要的概念:重做日志是用来写的(而不是用于读)。Oracle不会在正常的处理中读取重做日志。只要有足够的设备,使得ARCH读文件时,LGWR能写到另一个不同的设备,就不存在重做日志竞争。Oracle的目标是:可以顺序地写日志,而且在写日志时别人不会读日志。
本文来源 我爱IT技术网 http://www.52ij.com/jishu/5253.html 转载请保留链接。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
