在这里会介绍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代码  
  1. SQL> @mystat "redo size"
  2. NAME VALUE
  3. redo size 1016784
  4. SQL> insert into t select * from big_table; 已创建46990行。
  5. SQL> @mystat2
  6. NAME VALUE DIFF
  7. redo size 6604308 5,587,524
  8. 看到产生了5,587,524的REDO,再对比下用NOLOG插入
  9. SQL> @mystat "redo size"
  10. NAME VALUE
  11. redo size 6604308
  12. SQL> insert /*+ APPEND */ into t select * from big_table;
  13. 已创建46990行。
  14. SQL> @mystat2
  15. NAME VALUE DIFF
  16. redo size 6616220 11,912
SQL> @mystat "redo size" NAME VALUE
redo size 1016784 SQL> insert into t select * from big_table; 已创建46990行。 SQL> @mystat2
NAME VALUE DIFF
redo size 6604308 5,587,524
看到产生了5,587,524的REDO,再对比下用NOLOG插入 SQL> @mystat "redo size"
NAME VALUE
redo size 6604308 SQL> insert /*+ APPEND */ into t select * from big_table;
已创建46990行。 SQL> @mystat2
NAME VALUE DIFF
redo size 6616220 11,912 

看到APPEND插入用了11,912字节的REDO,比一般性插入要少很多。或者用这个PROCEDURE也可以观察SQL消耗的REDO.

Java代码  
  1. SQL>create or replace procedure do_sql( p_sql in varchar2 )
  2. as
  3. l_start_redo number;
  4. l_redo number;
  5. begin
  6. select v$mystat.value
  7. into l_start_redo
  8. from v$mystat, v$statname
  9. where v$mystat.statistic# = v$statname.statistic#
  10. and v$statname.name = 'redo size';
  11. execute immediate p_sql;
  12. commit;
  13. select v$mystat.value-l_start_redo
  14. into l_redo
  15. from v$mystat, v$statname
  16. where v$mystat.statistic# = v$statname.statistic#
  17. and v$statname.name = 'redo size';
  18. dbms_output.put_line
  19. ( to_char(l_redo,'9,999,999') ||' bytes of redo generated for "' ||
  20. substr( replace( p_sql, chr(10), ' '), 1, 25 ) || '"...' );
  21. end;
SQL>create or replace procedure do_sql( p_sql in varchar2 ) as l_start_redo number; l_redo number; begin 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_sql; commit; 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 ) || '"...' ); end; 

用法就不多说了。 减少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 database no force logging; 这两种方法转移数据时没有用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。

转载:http://blog.csdn.net/hdhai9451/archive/2009/02/27/3942051.aspx

二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) 系统就回到了原先的状态,没有这条记录了。

Oracle的REDO和UNDO相关推荐

  1. 大讲堂专访丨连接Oracle DBA与开发的桥梁:Oracle的redo与undo

    云和恩墨大讲堂每周都会邀请业内外大咖进行一小时的线上主题分享,本期我们邀请到了云和恩墨技术专家李元鹏,带来题为<浅谈Oracle的redo与undo>的分享,敬请期待. 在开课前,大讲堂对 ...

  2. Oracle 9 - redo和undo

    1.redo redo 有在线redo日志和归档redo日志, 从Oracle 10g开始还新增加了flashback技术. 每个Oracle数据库至少有2个在线重做日志组,循环写. 只有INSERT ...

  3. 【Oracle】redo与undo

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

  4. oracle的redo和undo,OracleUndoRedo通俗理解

    OracleUndoRedo通俗理解以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 什么是REDO REDO记录tran ...

  5. oracle的redo和undo,Oracle的redo 和undo的區別

    寫的次序: redo--> undo-->datafile insert一條記錄時, 表跟undo的信息都會放進 redo 中, 在commit 或之前, redo 的信息會放進硬盤上. ...

  6. oracle中redo和undo实验,REDO与UNDO几个实验

    1.IMU模式与非IMU模式下REDO的区别 1.1.IMU模式 REDO RECORD - Thread:1 RBA: 0x000004.0000000b.0010 LEN: 0x0374 VLD: ...

  7. Oracle redo 与 undo

    Oracle数据库中最重要的两部分数据:redo与undo.redo(重做信息)是oracle 在线(或归档)重做日志文件中记录的信息,万一出现失效时可以利用这些数据来"重放"(或 ...

  8. 【知识点整理】Oracle中NOLOGGING、APPEND、ARCHIVE和PARALLEL下,REDO、UNDO和执行速度的比较...

    [知识点整理]Oracle中NOLOGGING.APPEND.ARCHIVE和PARALLEL下,REDO.UNDO和执行速度的比较 [知识点整理]Oracle中NOLOGGING.APPEND.AR ...

  9. Oracle RBA(Redo Byte Address) 说明

    一. RBA 说明 之前整理了一个rdba和dba 的说明文档,参考: Oracle rdba和 dba 说明 http://blog.csdn.net/tianlesoftware/article/ ...

最新文章

  1. 【254天】跃迁之路——程序员高效学习方法论探索系列(实验阶段12-2017.10.17)...
  2. gin使用 GET, POST, PUT, PATCH, DELETE, OPTIONS
  3. VTK:可编程源用法实战
  4. Redis数据库(四)——Redis集群模式(主从复制、哨兵、Cluster)
  5. svn 单独导出某一个目录文件
  6. Java并发编程:volatile关键字解析(转载)
  7. Jaakko isalo谈《愤怒的小鸟》创意来源
  8. 计算机图形学_GAMES101-现代计算机图形学课程 全笔记
  9. 我奋斗了18年,不是为了和你一起喝咖啡。
  10. 创建 shell 脚本文件
  11. 【工作日记18】渗透测试之xml注入攻击、CRLF漏洞
  12. 基于STM32设计的校园一卡通项目-详解原理
  13. Root手机后有什么好处吗?我应该如何Root自己的手机?
  14. 头歌-软件测试技术-面向对象测试_王铁军
  15. APS计划排产软件在食品饮料行业的应用
  16. Baltimore System of Classifications of Viruses
  17. 机器学习中用到的概率知识_学习机器学习前,你首先要掌握这些概率论基础知识...
  18. [编程题]漂流船问题
  19. 报错:<generator object <genexpr> at 0x7fa9adc46eb0>
  20. 世界国家中英文对照表(json格式)

热门文章

  1. android编译VTS测试组件
  2. 一个测试工程师面试官的真实分享!个人超赞同!
  3. (王道408考研操作系统)第四章文件管理-第一节6:文件基本操作
  4. 第十一章 图形视图、动画、状态机框架
  5. Shell 判断文件或文件夹是否存在(不存在则创建)
  6. Windows端口占用情况?
  7. Python2、3字典比较函数
  8. twisted系列教程九–Deferred 的第二个小插曲
  9. Windows编程—Windows驱动开发环境搭建
  10. EOSIO:EOSIO最新版1.4.0 钱包开发环境搭建