redoredo log和undo log的区别

博客分类:
在这里会介绍UNDO,REDO是如何产生的,对TRANSACTIONS的影响,以及他们之间如何协同工作的。
什么是REDO REDO记录transaction logs,分为online和archived。以恢复为目的。 比如,机器停电,那么在重起之后需要online redo logs去恢复系统到失败点。 比如,磁盘坏了,需要用archived redo logs和online redo logs区恢复数据。 比如,truncate一个表或其他的操作,想恢复到之前的状态,同样也需要。 什么是UNDO REDO是为了重新实现你的操作,而UNDO相反,是为了撤销你做的操作,比如你得一个TRANSACTION执行失败了或你自己后悔了,则需要用ROLLBACK命令回退到操作之前。回滚是在逻辑层面实现而不是物理层面,因为在一个多用户系统中,数据结构,blocks等都在时时变化,比如我们INSERT一个数据,表的空间不够,扩展了一个新的EXTENT,我们的数据保存在这新的EXTENT里,其它用户随后也在这EXTENT里插入了数据,而此时我想ROLLBACK,那么显然物理上讲这EXTENT撤销是不可能的,因为这么做会影响其他用户的操作。所以,ROLLBACK是逻辑上回滚,比如对INSERT来说,那么ROLLBACK就是DELETE了。 COMMIT 以前,常想当然地认为,一个大的TRANSACTION(比如大批量地INSERT数据)的COMMIT会花费时间比短的TRANSACTION长。而事实上是没有什么区别的, 因为ORACLE在COMMIT之前已经把该写的东西写到DISK中了, 我们COMMIT只是 1,产生一个SCN给我们TRANSACTION,SCN简单理解就是给TRANSACTION排队,以便恢复和保持一致性。 2,REDO写REDO到DISK中(LGWR,这就是log file sync),记录SCN在ONLINE REDO LOG,当这一步发生时,我们可以说事实上已经提交了,这个TRANSACTION已经结束(在V$TRANSACTION里消失了) 3,SESSION所拥有的LOCK(V$LOCK)被释放。 4,Block Cleanout(这个问题是产生ORA-01555: snapshot too old的根本原因) ROLLBACK ROLLBACK和COMMIT正好相反,ROLLBACK的时间和TRANSACTION的大小有直接关系。因为ROLLBACK必须物理上恢复数据。COMMIT之所以快,是因为ORACLE在COMMIT之前已经作了很多工作(产生UNDO,修改BLOCK,REDO,LATCH分配), ROLLBACK慢也是基于相同的原因。 ROLLBACK会 1,恢复数据,DELETE的就重新INSERT,INSERT的就重新DELETE,UPDATE的就再UPDATE。 2,RELEASE LOCK ROLLBACK要比COMMIT消耗更多资源,因为ORACLE认为你一旦做数据更新,那么就意味着你要COMMIT(其他数据库不全是这种设计理念,比如DB2),所以在你更新数据的时候就做了大量的工作,这也可以理解为什么不建议用TABLE来做TEMPORARY TABLE。(TEMP TABLE消耗的REDO比固定表在INSERT时要少很多 ,UPDATE时差不多是1/2, 但是DELETE却相差无几) REDO 产生REDO 越多,你的系统越慢,不但影响你自己的SESSION,还影响其他SESSION,LGWR管理REDO,并且是TRANSACTION的结束标志。 首先要知道怎么监控REDO,当然,SET AUTOTRACE ON可以,不过只能监控DML语句,而像PROCEDURE则无法监视。那么我们就需要观察字典了,V$MYSTAT, V$STATNAME, 前面有两个脚本,mystat,mystat2
SQL& @mystat "redo size"
NAME VALUE
redo size 1016784
SQL& insert into t select * from big_ 已创建46990行。
SQL& @mystat2
NAME VALUE DIFF
redo size ,587,524
看到产生了5,587,524的REDO,再对比下用NOLOG插入
SQL& @mystat "redo size"
NAME VALUE
redo size 6604308
SQL& insert /*+ APPEND */ into t select * from big_
已创建46990行。
SQL& @mystat2
NAME VALUE DIFF
redo size ,912
看到APPEND插入用了11,912字节的REDO,比一般性插入要少很多。或者用这个PROCEDURE也可以观察SQL消耗的REDO.
SQL&create or replace procedure do_sql( p_sql in varchar2 )
select v$mystat.value
into l_start_redo
from v$mystat, v$statname
where v$mystat.statistic# = v$statname.statistic#
and v$statname.name = 'redo size';
execute immediate p_
select v$mystat.value-l_start_redo
into l_redo
from v$mystat, v$statname
where v$mystat.statistic# = v$statname.statistic#
and v$statname.name = 'redo size';
dbms_output.put_line
( to_char(l_redo,'9,999,999') ||' bytes of redo generated for "' ||
substr( replace( p_sql, chr(10), ' '), 1, 25 ) || '"...' );
用法就不多说了。 减少REDO 既然REDO这么消耗资源,那我们能屏蔽REDO吗?显然不能,那我们能减少REDO吗?这是可以的(注意,9.2以后,可以用FORCE LOGGING开关来控制是否强制REDO,如果YES,则不管NOLOGGING还是APPEND都是不起任何作用的,可以SELECT FORCE_LOGGING FROM V$DATABASE查看是否FORCE。另外需要明白,没有一个办法能彻底不记录REDO,只能是减少REDO。因为不管如何,数据字典总是要产生一些REDO的。 create table nologging as select xxx新建的表没有原来表的索引和默认值,只有非空(not null)的约束素条件可以继承过来. INSERT /*+ APPEND */ INTO target_tablename SELECT 如果运行此命令时还有对target_tablename的DML操作会排队在它后面,对OLTP系统在用的表操作是不合适的。快速插入数据可以指定append提示,但是需要注意 noarchivelog模式下,默认用了append就是nologging模式的。 在archivelog下,需要把表设置程Nologging模式。可以通过如下语句设置为NO FORCE LOGGING。 Alter datab 这两种方法转移数据时没有用SGA里数据缓冲区和事物处理的回滚段, 也不写联机事物日志,就象数据库装载工具SQLLOAD一样直接把数据写到物理文件。 REDO的问题
有时,会在ALERT中发现 Thread 1 cannot allocate new log, sequence 1466 Checkpoint not complete Current log# 3 seq# 1465 mem# 0: /home/ora10g/oradata/ora10g/redo03.log 这问题出现在系统尝试reuse online redo log file但是却没有可用的。可能是由于DBWR没有完成(Checkpoint not complete)或ARCH没有完成。 1,DBWR,用多DBWR process,合理分布数据, 2,增加REDO LOG FILE 3,扩大REDO的大小 4,让CHECKPOINT发生更频繁,可以减少block buffer cache,FAST_START_MTTR_TARGET, LOG_CHECKPOINT_INTERVAL,LOG_CHECKPOINT_TIMEOUT。
二REDO和UNDO的区别
redo--& undo--&datafile insert一条记录时, 表跟undo的信息都会放进 redo 中, 在commit 或之前, redo 的信息会放进硬盘上. 故障时, redo 便可恢复那些已经commit 了的数据. redo-&每次操作都先记录到redo日志中,当出现实例故障(像断电),导致数据未能更新到数据文件,则数据库重启时须redo,重新把数据更新到数据文件 undo-&记录更改前的一份copy,但你系统rollback时,把这份copy重新覆盖到原来的数据 redo-&记录所有操作,用于恢复(redo records all the database transaction used for recovery) undo-&记录所有的前印象,用于回滚(undo is used to store uncommited data infor used for rollback) redo-&已递交的事务,实例恢复时要写到数据文件去的 undo-&未递交的事务. redo的原因是:每次commit时,将数据的修改立即写到online redo中,但是并不一定同时将该数据的修改写到数据文件中。因为该数据已经提交,但是只存在联机日志文件中,所以在恢复时需要将数据从联机日志文件中找出来,重新应用一下,使已经更改数据在数据文件中也改过来!
undo的原因是:在oracle正常运行时,为了提高效率,加入用户还没有commit,但是空闲内存不多时,会由DBWR进程将脏块写入到数据文件中,以便腾出宝贵的内存供其它进程使用。这就是需要UNDO的原因。因为还没有发出commit语句,但是oracle的dbwr进程已经将没有提交的数据写到数据文件中去了。 undo 也是也是datafile, 可能dirty buffer 没有写回到磁盘里面去。只有先redo apply 成功了,才能保证undo datafile 里面的东西都是正确的,然后才能rollback 做undo的目的是使系统恢复到系统崩溃前(关机前)的状态,再进行redo是保证系统的一致性. 不做undo,系统就不会知道之前的状态,redo就无从谈起 所以instance crash recovery 的时候总是先rollforward, 再rollback undo 回退段中的数据是以“回退条目”方式存储。回退条目=块信息(在事务中发生改动的块的编号)+在事务提交前存储在块中的数据 在每一个回退段中oracle都为其维护一张“事务表” 在事务表中记录着与该回退段中所有回退条目相关的事务编号(事务SCN&回退条目) redo 重做记录由一组“变更向量”组成。每个变更变量中记录了事务对数据库中某个块所做的修改。
当用户提交一条commit语句时,LGWR进程会立刻将一条提交记录写入到重做日志文件中,然后再开始写入与该事务相关的重做信息。 #事务提交成功后,Oracle将为该事备生成一个系统变更码(SCN)。事务的SCN将同时记录在它的提交记录和重做记录中。
commit 提交事务前完成的工作:
·在SGA区的回退缓存中生成该事务的回退条目。在回退条目中保存有该事务所修改的数据的原始版本。
·在SGA区的重做日志缓存中生成该事务的重做记录。重做记录中记载了该事务对数据块所进行的修改,并且还记载了对回退段中的数据块所进行的修改。缓存中的重做记录有可能在事务提交之前就写入硬盘中。
·在SGA区的数据库缓丰中记录了事务对数据库所进行的修改。这些修改也有可能在事务提交之前就写入硬盘中。
提交事务时完成的工作:
·在为该事务指定的回退段中的内部事务表内记录下这个事务已经被提交,并且生成一个惟一的SCN记录在内部事务表中,用于惟一标识这个事务。
·LGWR后进进程将SGA区重做日志缓存中的重做记录写入联机重做日志文件。在写入重做日志的同时还将写入该事务的SCN。
·Oracle服务进程释放事务所使用的所有记录锁与表锁。
·Oracle通知用户事务提交完成。
·Oracle将该事务标记为已完成。
rollback 回退事务完成的工作:
·Oracle通过使用回退段中的回退条目,撤销事务中所有SQL语句对数据库所做的修改。
·Oracle服务进程释放事务所使用的所有锁
·Oracle通知事务回退成功。
·Oracle将该事务标记为已完成
举个例子: insert into a(id) values(1);(redo) 这条记录是需要回滚的。回滚的语句是delete from a where id = 1;(undo) 试想想看。如果没有做insert into a(id) values(1);(redo) 那么delete from a where id = 1;(undo)这句话就没有意义了。 现在看下正确的恢复: 先insert into a(id) values(1);(redo) 然后delete from a where id = 1;(undo) 系统就回到了原先的状态,没有这条记录了。
浏览 19515
浏览: 140587 次
来自: 广州
太厉害了,专门登陆支持一下楼主
我怎么还是没成功...
就是啊,为什么要替换包呢,难道你存在其它兼容问题?
楼主威武!我成功了用户名:sunwayle
文章数:99
评论数:93
访问量:311597
注册日期:
阅读量:1297
阅读量:3317
阅读量:461488
阅读量:1145851
51CTO推荐博文
&&&& 转自:[url]/jonescheng/archive//1189063.html[/url]
redo log& 重做日志/undo log & 撤消日志
重做日志:每当有操作执行前,将数据真正更改时,先前相关操作写入重做日志。这样当断电,或者一些意外,导致后续任务无法完成时,系统恢复后,可以继续完成这些更改
撤消日志:当一些更改在执行一半时,发生意外,而无法完成,则可以根据撤消日志恢复到更改之前的壮态
网上找到一些解说:以便以后自己参考
有两个概念:前滚与回退
比如某一时刻数据库DOWN机了,有两个事务,一个事务已经提交,另一个事务正在处理
数据库重启的时候就要根据日志进行前滚及回退,把已提交事务的更改写到数据文件,未提交事务的更改恢复到事务开始前的状态。
redo--& undo--&datafile
insert一条记录时, 表跟undo的信息都会放进 redo 中, 在commit 或之前, redo 的信息会放进硬盘上. 故障时, redo 便可恢复那些已经commit 了的数据.
redo-&每次操作都先记录到redo日志中,当出现实例故障(像断电),导致数据未能更新到数据文件,则数据库重启时须redo,重新把数据更新到数据文件
undo-&记录更改前的一份copy,但你系统rollback时,把这份copy重新覆盖到原来的数据
redo-&记录所有操作,用于恢复(redo records all the database transaction used for recovery)
undo-&记录所有的前印象,用于回滚(undo is used to store uncommited data infor used for rollback)
redo-&已递交的事务,实例恢复时要写到数据文件去的
undo-&未递交的事务.
redo的原因是:每次commit时,将数据的修改立即写到online
redo中,但是并不一定同时将该数据的修改写到数据文件中。因为该数据已经提交,但是只存在联机日志文件中,所以在恢复时需要将数据从联机日志文件中找
出来,重新应用一下,使已经更改数据在数据文件中也改过来!
undo的原因是:在oracle正常运行时,为了提高效率,加入用户还没有commit,但是空闲内存不多时,会由DBWR进程将脏块写入到数据
文件中,以便腾出宝贵的内存供其它进程使用。这就是需要UNDO的原因。因为还没有发出commit语句,但是oracle的dbwr进程已经将没有提交
的数据写到数据文件中去了。
undo 也是也是datafile, 可能dirty buffer 没有写回到磁盘里面去。
只有先redo apply 成功了,才能保证undo datafile 里面的东西都是正确的,然后才能rollback
做undo的目的是使系统恢复到系统崩溃前(关机前)的状态,再进行redo是保证系统的一致性.
不做undo,系统就不会知道之前的状态,redo就无从谈起
所以instance crash recovery 的时候总是先rollforward, 再rollback
回退段中的数据是以“回退条目”方式存储。
回退条目=块信息(在事务中发生改动的块的编号)+在事务提交前存储在块中的数据
在每一个回退段中oracle都为其维护一张“事务表”
在事务表中记录着与该回退段中所有回退条目相关的事务编号(事务SCN&回退条目)
重做记录由一组“变更向量”组成。
每个变更变量中记录了事务对数据库中某个块所做的修改。
当用户提交一条commit语句时,LGWR进程会立刻将一条提交记录写入到重做日志文件中,然后再开始写入与该事务相关的重做信息。
#事务提交成功后,Oracle将为该事备生成一个系统变更码(SCN)。事务的SCN将同时记录在它的提交记录和重做记录中。
提交事务前完成的工作:
?在SGA区的回退缓存中生成该事务的回退条目。在回退条目中保存有该事务所修改的数据的原始版本。
?在SGA区的重做日志缓存中生成该事务的重做记录。重做记录中记载了该事务对数据块所进行的修改,并且还记载了对回退段中的数据块所进行的修改。缓存中的重做记录有可能在事务提交之前就写入硬盘中。
?在SGA区的数据库缓丰中记录了事务对数据库所进行的修改。这些修改也有可能在事务提交之前就写入硬盘中。
提交事务时完成的工作:
?在为该事务指定的回退段中的内部事务表内记录下这个事务已经被提交,并且生成一个惟一的SCN记录在内部事务表中,用于惟一标识这个事务。
?LGWR后进进程将SGA区重做日志缓存中的重做记录写入联机重做日志文件。在写入重做日志的同时还将写入该事务的SCN。
?Oracle服务进程释放事务所使用的所有记录锁与表锁。
?Oracle通知用户事务提交完成。
?Oracle将该事务标记为已完成。
回退事务完成的工作:
?Oracle通过使用回退段中的回退条目,撤销事务中所有SQL语句对数据库所做的修改。
?Oracle服务进程释放事务所使用的所有锁
?Oracle通知事务回退成功。
?Oracle将该事务标记为已完成
举个例子:
insert into a(id) values(1);(redo)
这条记录是需要回滚的。
回滚的语句是delete from a where id = 1;(undo)
试想想看。如果没有做insert into a(id) values(1);(redo)
那么delete from a where id = 1;(undo)这句话就没有意义了。
现在看下正确的恢复:
先insert into a(id) values(1);(redo)
然后delete from a where id = 1;(undo)
系统就回到了原先的状态,没有这条记录了。
了这篇文章
类别:┆阅读(0)┆评论(0)
11:38:36 14:42:07您所在位置: &
&nbsp&&nbsp&nbsp&&nbsp
REDOLOG與UNDOLOG这两个概念的区别.docx 9页
本文档一共被下载:
次 ,您可全文免费在线阅读后下载本文档。
下载提示
1.本站不保证该用户上传的文档完整性,不预览、不比对内容而直接下载产生的反悔问题本站不予受理。
2.该文档所得收入(下载+内容+预览三)归上传者、原创者。
3.登录后可充值,立即自动返金币,充值渠道很便利
需要金币:150 &&
REDOLOG與UNDOLOG这两个概念的区别
你可能关注的文档:
··········
··········
REDO LOG 与 UNDO LOG这两个概念的区别--转载转自:[url]/jonescheng/archive//1189063.html[/url]redo log 重做日志/undo log 撤消日志重做日志:每当有操作执行前,将数据真正更改时,先前相关操作写入重做日志。这样当断电,或者一些意外,导致后续任务无法完成时,系统恢复后,可以继续完成这些更改撤消日志:当一些更改在执行一半时,发生意外,而无法完成,则可以根据撤消日志恢复到更改之前的壮态网上找到一些解说:以便以后自己参考有两个概念:前滚与回退比如某一时刻数据库DOWN机了,有两个事务,一个事务已经提交,另一个事务正在处理数据库重启的时候就要根据日志进行前滚及回退,把已提交事务的更改写到数据文件,未提交事务的更改恢复到事务开始前的状态。redo--& undo--&datafileinsert一条记录时, 表跟undo的信息都会放进 redo 中, 在commit 或之前, redo 的信息会放进硬盘上. 故障时, redo 便可恢复那些已经commit 了的数据.redo-&每次操作都先记录到redo日志中,当出现实例故障(像断电),导致数据未能更新到数据文件,则数据库重启时须redo,重新把数据更新到数据文件undo-&记录更改前的一份copy,但你系统rollback时,把这份copy重新覆盖到原来的数据redo-&记录所有操作,用于恢复(redo records all the database transaction used for recovery)undo-&记录所有的前印象,用于回滚(undo is used to store uncommited data infor used for rollback)redo-&已递交的事务,实例恢复时要写到数据文件去的 undo-&未递交的事务.redo的原因是:每次commit时,将数据的修改立即写到online redo中,但是并不一定同时将该数据的修改写到数据文件中。因为该数据已经提交,但是只存在联机日志文件中,所以在恢复时需要将数据从联机日志文件中找出来,重新应用一下,使已经更改数据在数据文件中也改过来!undo的原因是:在oracle正常运行时,为了提高效率,加入用户还没有commit,但是空闲内存不多时,会由DBWR进程将脏块写入到数据文件中,以便腾出宝贵的内存供其它进程使用。这就是需要UNDO的原因。因为还没有发出commit语句,但是oracle的dbwr进程已经将没有提交的数据写到数据文件中去了。undo 也是也是datafile, 可能dirty buffer 没有写回到磁盘里面去。只有先redo apply 成功了,才能保证undo datafile 里面的东西都是正确的,然后才能rollback做undo的目的是使系统恢复到系统崩溃前(关机前)的状态,再进行redo是保证系统的一致性. 不做undo,系统就不会知道之前的状态,redo就无从谈起所以instance crash recovery 的时候总是先rollforward, 再rollbackundo回退段中的数据是以“回退条目”方式存储。回退条目=块信息(在事务中发生改动的块的编号)+在事务提交前存储在块中的数据在每一个回退段中oracle都为其维护一张“事务表”在事务表中记录着与该回退段中所有回退条目相关的事务编号(事务SCN&回退条目)redo重做记录由一组“变更向量”组成。每个变更变量中记录了事务对数据库中某个块所做的修改。当用户提交一条commit语句时,LGWR进程会立刻将一条提交记录写入到重做日志文件中,然后再开始写入与该事务相关的重做信息。#事务提交成功后,Oracle将为该事备生成一个系统变更码(SCN)。事务的SCN将同时记录在它的提交记录和重做记录中。commit提交事务前完成的工作:·在SGA区的回退缓存中生成该事务的回退条目。在回退条目中保存有该事务所修改的数据的原始版本。·在SGA区的重做日志缓存中生成该事务的重做记录。重做记录中记载了该事务对数据块所进行的修改,并且还记载了对回退段中的数据块所进行的修改。缓存中的重做记录有可能在事务提交之前就写入硬盘中。·在SGA区的数据库缓丰中记录了事务对数据库所进行的修改。这些修改也有可能在事务提交之前就写入硬盘中。提交事务时完成的工作:·在为该事务指定的回退段中的内部事务表内记录下这个事务已经被提交,并且生成一个惟一的SCN记录在内部事务表中,用于惟一标识这个事务。·LGWR后进进程将SGA区重做日志缓存中的重做记录写入联机重做日志文件。在写入重做日志的同时还将写入该事务的SCN
正在加载中,请稍后...
58页72页51页67页48页40页65页46页64页74页查看:15624|回复:2
初级工程师
UNDO和REDO表空间&&
弄懂几个概念:
redo是重做日志文件,是oracle数据库的日志文件.oracle的重做日志有两种:在线重做日志以及归档重做日志。
在线重做日志:主要用于由于数据库主机掉电等原因导致实例失败,此时oracle采用在线重做日志在数据库启动时将数据库恢复到归档重做日志:主要用于介质失败,比如:磁盘受损。此时需要使用对磁盘上的数据备份的归动重做日志文件将该磁盘上的数据恢复到该归档文件数据所在的时间点上,然后再使用在线重做日志文件将适合的时间点上。
归档重做日志文件实质是被添满的旧的在线重做日志的副本。归档重做日志文件是数据库的历史数据。
在线重做日志在每个数据库中至少有两个重做日志组,每个日志组中至少有一个重做日志文件,这些在线重做日志组是循环使用的,当日志组1被写到最后时,然后自动切换到日志组2;当日志组2也被写满时,再切换到日志组1。
undo与redo相反,redo是恢复数据,用于在事务失败时重放事务,undo是撤消一条语句或者一组语句的作用。undo是存储在数据库内部的段或者表空间中(undo如果是手动管理,则使用undo段来管理;如果undo使用AUM管理UNDO,则undo使用表空间来自动管理)。
注意:在undo并不是物理的恢复到执行语句之前或者事务之前的样子,只是逻辑的恢复到原来的样子,所有修改只是逻辑的取消,但是数据结构和数据块在回滚之后也大不相同。原因是在多用户系统中,有很多事务是并发进行的,当一个事务修改一个数据并且被回滚,但是该数据在该用户对该数据做过修改之后也也有被其他用户修改,这个时候如果是对该事务修改的数据块回滚到原来数据的物理样子,就有可能将后来的事务所做的修改给覆盖掉。所以回滚不是一个简单的物理的恢复,而是逻辑恢复。
例如:做下面的步骤:
表已删除。
SQL& create table t
表已创建。
SQL& select *
SQL& set autotrace traceonly statistics
SQL& select *
----------------------------------------------------------
& && &&&992&&bytes sent via SQL*Net to client
& && &&&374&&bytes received via SQL*Net from client
& &&&1&&SQL*Net roundtrips to/from client
注意:在每个用例做2次全表扫描,这样是为了避免解析和优化期间优化器可能产生的额外的I/O,测试只需要比较第二次的查询情况
SQL& insert into t select * from all_
-----------------------------------------------------
& && &&&676&&bytes sent via SQL*Net to client
& && &&&575&&bytes received via SQL*Net from client
& && && & 4&&SQL*Net roundtrips to/from client
回退已完成。
SQL& select *
SQL& set autotrace traceonly statistics
SQL& select *
----------------------------------------------------------
& && &&&992&&bytes sent via SQL*Net to client
& && &&&374&&bytes received via SQL*Net from client
& && && & 1&&SQL*Net roundtrips to/from client
分析:在进行插入操作的时候数据库为该表分配可新的数据块,表示表所占用的空间变大。进行插入操作,表得到新的数据块,然后格式化新的数据块,然后准备放数据进入;此时另一个事务是回滚这些数据,此时回滚并不能将新分配给表的空间给撤消掉,也不能取消对数据块的格式化操作,实际做的是与原来的逻辑相反的工作,insert操作相反的操作是delete,delete相反的操作是insert操作,操作相反的操作是另外执行一个update操作将其变为原来的行。
undo信息是存放在UNDO表空间或者UNDO段中,也会受REDO保护,即表示会将UNDO数据当做表数据或者是索引数据一样,对UNDO的修改也会产生一些REDO,这些REDO信息也会被记录到日志中去。为什么会这样?在下面讲解系统崩溃发生的情况会解释。undo数据会被加到UNDO段
有下面的三句语句:
insert into t(x,y)values(1,1);
update t set x=x+1 where x=1;
delete from t where x=2;
假设沿着不同的路径完成这个事务,得到不同的答案:
路径1:如果系统在处理这些语句的不同时间点上失败,会发生什么情况;
对于第一条语句进行的insert into语句,redo和undo都会生成。所生成的UNDO足以撤消insert操作的作用;所生成的REDO可以使这个插入操作再次复现;
图中显示了缓存中存放的已经被修改的UNDO块,索引块和表数据块,这些数据块都得到了重做日志缓冲区中相应的redo项保存;
系统现在崩溃没有关系。SGA会被清空,但是SGA中的内容我们并不需要。因为在系统重新启动时就好象这个事务没有发生过一样。没有任何已修改的块刷新输出到磁盘,也没有任何REDO刷新输出到磁盘,这样就不需要这些undo和redo信息来实现实例恢复;
由于缓存区已满,所以DBWR进程需要将已修改的数据块从缓存中刷新写入磁盘中去来留出空闲的空间。如果是这样,DBWR首先是要求LGWR进程将这些已被修改的数据块的相关的REDO条目信息先刷新写入重做日志文件中去。DBWR在做任何将已被修改的数据块写进磁盘中之前,都要做首先通知LGWR进程先将这些块相关的REDO信息写入重做日志文件中去。假设没有这样的话,在DBWR将被修改的数据块写进磁盘之前没有通知LGWR进程将REDO信息写进重做日志文件,一旦系统失败的话,就只有被修改的数据,而没有与之相关的REDO信息而造成系统不能很好的恢复。但是如果进行了通知LGWR进程先将这些块相关的REDO信息写入重做日志文件中去的话,这样就能够重做所有的修改,将SGA恢复到系统失败前的状态,从而可以成功回滚。
从图1中可以看出,生成的被修改的书数据块和索引块,以及与这些被修改的数据块相关的UNDO段块,这三部分都会生成REDO来保护自己的。
重做日志缓冲区刷新输出的条件:
每3秒一次;缓冲区达到1/3满时;或者包含1M的缓冲数据;或者是只要发生事务提交就会发生刷新输出;重做日志缓冲区很有可能会在处理期间的某个时间点上刷新输出,并且刷新输出的状态是如图2:
Update所带来的工作和Insert大体一样。不过Update生成的undo量更大;由于是更新,需要保存更新前的数据,即“前”映象。
块缓冲区中会有更多新的UNDO块,为了也能够撤消这个更新,如果有必要,已修改的数据库整张表和索引块也会放到缓存中,也会生成更多的重做日志缓冲区条目。下面假设前面的插入语句生成了一些重做日志,有部分被写进重做日志文件中,但是还有一些仍存放在缓存中。
该场景涵盖了系统崩溃恢复的基本细节。系统将其作为一个2步的过程来完成。首先前滚,将系统放到失败的点上,然后回滚尚未提交的所有工作,这个动作会再次同步数据文件。它会重放已经进行的工作,并撤消尚未完成的所有工作。
第一步:前滚,将系统放到失败的时间点上:
系统启动时,系统会读取重做日志,发现有相关的事务的一些重做日志条目。给定系统的当前状态,利用重做日志文件中对应插入的REDO条目,还有仍在缓冲区中的一些对应的REDO信息,oracle会前滚插入;(前面讲系统崩溃,SGA被清空,那么在这里应该也会清空缓冲区中的REDO信息的呀?但是为什么还仍然继续存在?这里的缓冲区不在SGA中吗?)前滚得到图1中的状态。
第二步:如果发现前面的插入操作还没有提交,并且这个插入语句对应的UNDO块(用于撤消插入),已修改的表块(刚插入后的状态),以及已修改的索引块(刚插入后的状态),此时系统会使用上面的这些UNDO信息来回滚。系统取刚刚在缓冲区缓存中前滚得到的UNDO,并将这些UNDO应用到数据块和索引块,使数据块和索引块恢复到插入前的系统状态。这样回到插入前的状态,但是在磁盘上的块可能会反映插入后的数据,也可能不反映(这个取决于崩溃前DBWR是否进行块刷新输出将数据写进磁盘)。如果磁盘中的块确实反映了插入,而实际上插入已经被撤消。此时这个只有在当缓冲区缓存刷新输出块时,数据文件就会被重新写,使得数据文件反映出插入已撤消。如果磁盘上的块没有反映前面的插入,就不用管它-这些块以后会被覆盖。
假设场景:应用回滚事务
Oracle发现这个事务的UNDO信息可能在缓存的UNDO段中块中(基本上这样),也可能这个事物的UNDO信息已经被刷新写进磁盘中去(当大事务会有这种情况发生)。系统会将UNDO信息应用到缓冲区缓存中的数据块和索引块上,或者如果这些需要回滚的数据块已经不在缓存中,则就需要从磁盘中将对应的数据和索引块读入缓存,再对其进行应用UNDO。这些块会恢复为原来的行值,并刷新输出到数据文件写进磁盘中去。
需要指出一点:回滚过程不涉及对重做日志,只有在恢复和归档时才会读取重做日志。Oracle在正常情况下,不会重做日志进行读取操作。Oracle的目标是:可以顺序地写日志,而且在写日志时别人不会读日志,这样主要是为了提高性能和避免资源竞争。
DELETE会生成UNDO,块被修改,并且将REDO写到重做日志缓冲区中。这个与前面的UPDATE差不多。
COMMIT,此时oracle会将日志缓冲区刷新输出到磁盘中去。如图4:
已修改的数据块或者还在缓冲区缓存中;也有可能被写进磁盘中去。但是重做这个事务的所有REDO信息都被写进磁盘中去,此时就表示这个数据的修改是永久的了。如果有读取文件中的数据不是事务发生之后的样子,这个是由于DBWR还没有立即写进磁盘的原因,这个不要紧。如果出现读取失败,可以通过重做日志文件来得到最新的块信息。UNDO信息也存在(除非UNDO被重用),UNDO信息存在就可以保证数据的一致性,可以回滚到过去某个时间点上的数据。
COMMIT操作是一个很快的操作,并且每个COMMIT操作其响应的时间或多或少是平均的,不管事务的大小。
取决于前三项的大小,以及这些花费的时间,前面的某个数据(或者是某些数据)被刷新 写入磁盘;
*LGWR将所有余下的缓存重做日志条目写到磁盘中,并将SCN记录到在线虫做日志文件中,这步的完成表示事务提交的真正完成。此时,事务条目会从V$TRANSACTION视图中删除掉,表示事务已经提交;
*如果事务修改的数据块还有部分还没有写入磁盘,则会一种快速的模式访问并“清理“。块清理(block cleanout)是指清除存储在数据库首部的与锁相关的信息。实质是清除块上的事务信息。这样下一个访问这个块的人就不用再做块清理了操作了。这种是采用一种无需生成重做日志信息的方式来完成块清除。
由上可以看出,处理CMMIT操作所要的做的工作很少,耗时最长的是LGWR执行的将REDO写进磁盘的操作,因为这个操作进行了物理磁盘I/O。但是CMMIT又是很快的原因是在于LGWR在你的工作期间一直在以连续的方式将重做日志缓冲区的内容写进磁盘中,同时LGWR也一直在以增量的方式来不停的刷新重做日志缓冲区中的内容。这样避免一次性将大量REDO写进磁盘操作使提交等待很长时间。
Rollback与commit相反,它是一个与被修改的数据量有关的一个函数。被修改的数据量越大,rollback所需要的时间越长。
取决于前三项的大小,以及这些花费的时间,前面的某个数据(或者是某些数据)被刷新 写入磁盘;
*撤消已做的所有修改。其完成方式如下:从UNDO中读回数据,然后逆向执行前面所做的操作,并且将UNDO条目记为已用。如果先前是插入,rollback会将删除,如果是更新了一行,则回滚就撤消这个更新操作;如果是删除了一行,则回滚就需要插入一行。
引文来源&&
redo不是表空间啊
何乡是吾乡,归期未有期 ...
redo确实不是表空间
以大多数人的努力程度之低,根本轮不到拼天赋}

我要回帖

更多关于 redo和undo日志 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信