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将同时记录在它的提交记录和重做记录中。


redo(重做信息)是Oracle在在线(或归档)重做日志文件中记录的信息,万一出现失败时可以利用这些数据来“重放”(或重做)事务。

Oracle维护着两类重做日志文件:在线(online)重做日志文件和归档(archived)重做日志文件。
数据库所在主机掉电,导致实例失败,Oracle会使用在线重做日志将系统恰好恢复到掉电之前的那个时间点。
如果磁盘驱动器出现故障(这是一个介质失败),Oracle会使用归档重做日志以及在线重做日志将该驱动器上的数据备份恢复到适当的时间点。
归档重做日志文件实际上就是已填满的“旧”在线重做日志文件的副本

undo(撤销信息)是Oracle在undo段中记录的信息,用于取消或回滚事务。


redo与undo协作:
insert,updata,delete语句都会生成redo和undo。

提交和回滚处理:

commit之前数据库已经完成的工作:
1已经在SGA中生成了undo块。
2已经在SGA中生成了已修改数据块。
3已经在SGA中生成了对于前两项的缓存redo。
4取决于前三项的大小,以及这些工作花费的时间,前面的每个数据(或某些数据)可能已经刷新输出到磁盘。
5已经得到了所需的全部锁。
commit的工作:
1为事务生成一个SCN。SCN是Oracle使用的一种简单的计时机制,用于保证事务的顺序,并支持失败恢复。SCN还用于保证数据库中的读一致性和检查点。可以把SCN看作一个钟摆,每次有人COMMIT时,SCN都会增1.
2LGWR将所有余下的缓存重做日志条目写到磁盘,并把SCN记录到在线重做日志文件中。如果出现了这一步,即已经提交。事务条目会从V$TRANSACTION中“删除”,这说明我们已经提交。
3V$LOCK中记录这我们的会话持有的锁,这些所都将被释放,而排队等待这些锁的每一个人都会被唤醒,可以继续完成他们的工作。
4如果事务修改的某些块还在缓冲区缓存中,则会以一种快速的模式访问并“清理”。
rollback的工作:
1撤销已做的所有修改。其完成方式如下:从undo段读回数据,然后实际上逆向执行前面所做的操作,并将undo条目标记为已用。如果先前插入了一行,ROLLBACK会将其删除。如果更新了一行,回滚就会取消更新。如果删除了一行,回滚将把它再次插入。
2会话持有的所有锁都将释放,如果有人在排队等待我们持有的锁,就会被唤醒。

测量redo
mystat.sql统计初始值(如redo大小)保存在一个SQL*Plus变量中:
set verify off
column value new_val V
define S="&1"
set autotrace off
select a.name, b.value
from v$statname a, v$mystat b
where a.statistic# = b.statistic#
and lower(a.name) like '%' || lower('&S')||'%'

mystat2.sql脚本只是打印出该统计的初始值和结束值之差:
set verify off
select a.name, b.value V, to_char(b.value-&V,'999,999,999,999') diff
from v$statname a, v$mystat b
where a.statistic# = b.statistic#
and lower(a.name) like '%' || lower('&S')||'%'

执行:
@mystat "redo size"
@mystat2


关闭redo不是不生成日志,而是减少生成日志。
方法有:
1把NOLOGGING关键字潜在SQL命令中
2在段(索引或表)上设置NOLOGGING属性,从而隐式地采用NOLOGGING模式来执行操作。例如,可以把一个索引或表修改为默认采用NOLOGGING模式。这说明,以后重建这个索引不会生成日志(其他索引和表本身可能还会生成redo,但是这个索引不会);

可以采用nologging模式执行的操作。
1索引的创建和ALTER(重建)。
2表的批量INSERT(通过/*+APPEND */提示使用“直接路径插入“。或采用SQL*Loader直接路径加载)。表数据不生成redo,但是所有索引修改会生成redo,但是所有索引修改会生成redo(尽管表不生成日志,但这个表上的索引却会生成redo!)。
3LOB操作(对大对象的更新不必生成日志)。
4通过CREATE TABLE AS SELECT创建表。
5通过CREATE TABLE AS SELECT创建表。

临时表和redo/undo:
修改临时表中的一个块时,不会将这个修改记录到重做日志文件中。不过,临时表确实会生成undo,而且这个undo会计入日志。因此,临时表也会生成一些redo。

在临时表上的DML操作:
1INSERT会生成很少甚至不生成undo/redo活动。
2DELETE在临时表上生成的redo与正常表上生成的redo同样多。
3临时表的UPDATE会生成正常表UPDATE一半的redo。

undo生成的大小一般来讲,
INSERT生成的undo最少,因为Oracle为此需记录的只是要“删除”的一个rowid(行ID)。
UPDATE一般排名第二(在大多数情况下)。对于UPDATE,只需记录修改的字节。你可能只更新(UPDATE)了整个数据行中很少的一部分,这种情况最常见。因此,必须在undo中记录行的一小部分。
与加索引列的更新相比,对一个未加索引的列进行更新不仅执行得更快,生成的undo也会好得多。
DELETE生成的undo最多。对于DELETE,Oracle必须把整行的前映像记录到undo段中。

猜你喜欢

转载自blog.csdn.net/tan88881111/article/details/80762313
今日推荐