精华内容
下载资源
问答
  • insert一条记录时, 表跟undo的信息都会放进 redo , 在commit 或之前, redo 的信息会放进硬盘上. 故障时, redo 便可恢复那些已经commit 了的数据. redo->每次操作都先记录到redo日志,当出现实例故障(像断电)...
    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)
    系统就回到了原先的状态,没有这条记录了
    展开全文
  • oracleredo和undo

    2017-07-31 16:46:11
    下面详细描述了undo 的DML操作是如何保存在undo tablespace在线归档日志的。然后在分析下undo保存两份信息的原因。 首先,看看undo是如何保存在undo tablespace的。 –oracle redo 包含 undo – ...
    
    oracle实例在crash后,undo如何恢复的比较难于理解。下面详细描述了undo 的DML操作是如何保存在undo tablespace和在线归档日志中的。然后在分析下undo保存两份信息的原因。

    首先,看看undo是如何保存在undo tablespace中的。
    –oracle redo 包含 undo
    – Checkpointing 导致
    . 脏块被写到数据文件中
    . 同样的包含undo信息的buffers 也被写到undo tablespace


    概述:
    – 创建tablespace test_undo
    – 创建表 test_undo_tab in tablespace test_undo
    – Insert two rows with txt – teststring1, teststring2 in test_undo_tab 然后执行checkpoint。
    – 切换日志,新在线日志中没有包含string teststring1
    – 切换undo表空间到表空间undotbs2
    – 将字段从 teststring1 更新为teststring_uncommitted,但是不commit
    – 在另外一个会话,将字段值从 teststring2 更新为teststring_committed并commit。
    – 检查是不是字段的修改前后的值都写到现在的redo log文件中。
    – 检查undo表空间没有包含修改前的值,例如:
    teststring1 和 teststring2 作为undo信息还在buffer cache中,checkpoint还没有发生。
    – 执行手工的checkpoint,buffers中的信息包含undo信息都会刷新到磁盘中。
    – 检查undo表空间是否包含修改前的值。例如teststring1 和 teststring2



    执行:

    – 正在使用的undo tablespace –
    sql>sho parameter undo_tablespace
    NAME                                 TYPE        VALUE
    -----------------------------------------------
    ------------------------------
    undo_tablespace                      string      UNDOTBS1

    – 创建一个新的undo表空间undotbs2
    SQL> create undo tablespace undotbs2datafile '/paic/app/dbshare/undotbs2.dbf'
    size 100m;

    – 创建一个表空间test_undo
    SQL> drop tablespace test_undo includingcontents and datafiles;
        create tablespace test_undo datafile '/paic/app/dbshare/test_undo.dbf' size 128k;

    – 在上面创建的表空间中创建测试表test_undo_tab
    SQL> drop table test_undo_tab purge;
        create table test_undo_tab(txt char(1000)) tablespace test_undo;

    – 在test_undo_tab表中insert两条记录并commit –
    SQL> insert into test_undo_tab values('teststring1');
        insert into test_undo_tab values ('teststring2');
        commit;

    – 执行手工checkpoint,然后上述修改写到数据文件中。
    SQL>alter system checkpoint;

    - 将当前的undo表空间切换为undotbs2
    SQL>alter system set undo_tablespace =undotbs2;
       show parameter undo_tablespace
    NAME                                 TYPE        VALUE
    -----------------------------------------------
    ------------------------------
    undo_tablespace                      string      UNDOTBS2

    – 切换redo log,这样当前的redolog没有包含任何信息。
    SQL>alter system switch logfile;

    – 找出现有的redo log
    SQL> col member for a30
        select member, l.status from v$log l, v$logfile f where l.group# =f.group# and l.status = 'CURRENT';

    MEMBER                         STATUS
    ----------------------------------------------
    +DATA_TEST1_DG/test/onlinelog CURRENT
    /group_2.384.865438859     

    – 打开一个会话更新一条记录但是不commit–
    SQL> update test_undo_tab set txt = 'teststring_uncommitted'
         where txt = 'teststring1';

    – 打开另外一个会话,修改第二条记录,并commit –
    SQL> update test_undo_tab set txt = 'teststring_committed'
         where txt = 'teststring2';
         commit;

    – 然后检测redo log文件中是否包含redo和undo的DML操作 (committed and uncommitted)–
    [grid@cnsh230235 ~]$ asmcmd cp+DATA_TEST1_DG/weiyj/onlinelog/group_3.401.865438859 /oracle_grid/grid/group_2
    copying+DATA_TEST1_DG/weiyj/onlinelog/group_2.384.865438859 ->/oracle_grid/grid/group_2
    [grid@cnsh230235 ~]$ strings group_2 |greptest  
    teststring_uncommitted                                                                                                                                                                                                                                               
    teststring1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
    teststring_committed                                                                                                                                                                                                                                                                                                         
    teststring2                                                                                                                                                                                                                                       

    – 检测数据文件没有包含修改的值,比如teststring_committed 和 teststring_uncommitted ,因为checkpoint还没有发生,脏块还没有写入到磁盘。
    [oracle@node1 oracle]$ strings/u01/app/oracle/test_undo.dbf|grep teststring

    teststring2                                                                                                                             ,
    teststring1

    – 检测undo表空间也没有包含更新前的值,比如undo的信息teststring1 和teststring2还在buffer cache中,checkpointing还没有发生。
    [oracle@node1 oracle]$ strings/u01/app/oracle/undotbs2.dbf|grep teststring

    – 执行手工的checkpoint,这样buffers中的undo信息就被刷新到磁盘中。
    SQL> alter system checkpoint;

    – 检测数据文件包含了修改前后的值,(both committed anduncommitted) ,例如: teststring_committed andteststring_uncommitted,因为checkpointing发生后, buffers中的脏块被刷新到磁盘中。
    [oracle@node1 oracle]$ strings/u01/app/oracle/test_undo.dbf|grep teststring

    teststring_committed                                                                                                              ,
    teststring_uncommitted

    – 检测undo表空间中也包含了修改前的值,比如teststring1 and teststring2
    [oracle@node1 oracle]$ strings/u01/app/oracle/undotbs2.dbf| grep teststring

    teststring2                                                                 
    teststring1

    – 清理测试文件 –
    SQL>drop tablespace test_undo includingcontents and datafiles;
       alter system set undo_tablespace=undotbs1;
       drop tablespace undotbs2 including contents and datafiles;


    现在可以得出结论:

    –Log writer 会写一个事务中每个DML的undo和redo (committed/uncommitted) 和是否发生checkpoint没有关系。
    – 发生checkpoint时,
    . database buffer cache中的undo信息会写到undo表空间中
    . 脏块Dirty buffers中包含了committed/uncommitted数据会被写入到数据文件中。


    如果是一个正在运行中数据库,这意味着:
    – 数据文件可能会包含未提交的信息 (被修改的buffers、但是没有commited、发生checkpoint)
    – 提交的数据没有在数据文件中(提交后,checkpointing还没有发生)
    – 修改后提交的redo/undo会被写入到redo logs中 (Lgwr writes on commit).
    – 修改后没有提交的redo/undo可能被写入到redo logs中(Lgwr writes every 3 seconds)
    – 除了redo logs文件,undo information
    § .
    可能会在buffer cache中 (修改后checkpoint还没有发生)
    § . checkpoint发生后会被写入到undo表空间中。
    § . 当一个事物活动、没有结束时,undo信息是不会被覆盖的。


    另外一个问题时,为什么undo信息需要保存两份,分别保存在undo表空间和redo logs文件中。


    让我们看看如果undo信息只保存在redo log文件中,会发生什么情况。

    只要修改的数据已经写到数据文件中,redo log可以被重用。


    如果进行了修改,但是没有commit的情况下:
    – 修改被写到了redo log文件中
    – 发生了checkpoint
    – uncommitted的修改被写到了数据文件中
    – 如果决定回退修改
    – 如果redo log文件没有被覆盖重用
    . 搜索整个redo log文件,然后进行回退
    如果覆盖重用了
    . undo的信息就不能进行恢复了。


    有人可能会说,如果redo log包含了活动的undo信息,就不允许覆盖重用, 我们就可能只需要保存undo到redo log文件中了。这种方案也是不可行的,因为:
    – redo log文件的大小将会增至的非常大,因为极端情况下,一个用户可能过几个月才结束一个事务。
    – 为了回退一个修改,需要读取大量redo log文件中的数据,包括redo和undo信息,这将带来性能极大的下降。
    – redo log文件将会出现争用,因为它们被用作:
    . 同时写 redo and undo
    . 用来读取回退修改

    所以,undo信息除redo log之外还需要独立保存用来回退没有commit的事务。Undo信息会保存在undo buffers/undo tablespace中,用来:
    – read consistency
    – flashback query
    – flashback version query


    现在, 让我们看看如果undo只保存在undo表空间中,会出现什么情况。


    情况– I
    – 进行修改但是没有提交
    – 修改的redo信息保存在redo log文件中
    – 修改的undo信息保存在buffer cache
    – 修改的undo信息还没有保存到undo表空间中,因为还没有发生checkpoint
    – 实例 crashes
    – 保存在buffer cache的undo信息被清除了。
    – 作为instance recovery的一部分, redo被应用后,数据文件保护了未commit的数据。
    – 数据库不能被打开,因为没有undo信息来需要回退未提交的修改,这样数据库处于不一致的状态。


    情况– II
    – 进行表空间的hot backup
    – 表空间的数据库文件丢失或者损坏了
    – 将表空间offline,然后从备份restore数据文件
    – recover the datafile
    – redo logs和archivelogs包含了提交和未提交事务的redo数据
    – redo logs和archivelogs没有包含undo的信息(根据假设).
    – 作为recovery的一部分, 提交和未提交事务的redo数据可以读取并应用。
    – 表空间还是不能修改为在线,因为需要进行回滚的undo信息没有找到。


    所以,为了解决上面的问题,undo也需要保存在redo log文件中。在实例或者media recovery时,进行向前回滚,redo的信息(redo log文件中)被应用到数据文件,undo的信息被用来生成undo segments。在实例或者media recovery时,进行向后回滚,这些undo segments后续被用来做回退没有提交的修改。
    展开全文
  • oracle_redo_undo

    2011-01-08 12:01:41
    oracle_redo_undo
  • OracleREDO和UNDO

    2015-01-21 14:38:34
    在这里会介绍UNDOREDO是如何产生的,对TRANSACTIONS的影响,以及他们之间如何协同工作的。  什么是REDO  REDO记录transaction logs,分为onlinearchived。以恢复为目的。 比如,机器停电,那么在重起之后...

    转载:http://meng702.iteye.com/blog/1008638

    在这里会介绍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

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

    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.   
    12. execute immediate p_sql;   
    13. commit;   
    14.   
    15. select v$mystat.value-l_start_redo   
    16. into l_redo   
    17. from v$mystat, v$statname   
    18. where v$mystat.statistic# = v$statname.statistic#   
    19. and v$statname.name = 'redo size';   
    20.   
    21. dbms_output.put_line   
    22. ( to_char(l_redo,'9,999,999') ||' bytes of redo generated for "' ||   
    23. substr( replace( p_sql, chr(10), ' '), 1, 25 ) || '"...' );   
    24. 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://meng702.iteye.com/blog/1008638

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

     

    展开全文
  • oracleredo和undo

    2016-02-29 21:43:15
     在这里会介绍UNDOREDO是如何产生的,对TRANSACTIONS的影响,以及他们之间如何协同工作的。  什么是REDO  REDO记录transaction logs,分为onlinearchived。以恢复为目的。  比如,机器停电,那么在重...

    来自http://www.inthirties.com/thread-239-1-1.html

     

     在这里会介绍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_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 

    引用:
    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 
    12 execute immediate p_sql; 
    13 commit; 
    14 
    15 select v$mystat.value-l_start_redo 
    16 into l_redo 
    17 from v$mystat, v$statname 
    18 where v$mystat.statistic# = v$statname.statistic# 
    19 and v$statname.name = 'redo size'; 
    20 
    21 dbms_output.put_line 
    22 ( to_char(l_redo,'9,999,999') ||' bytes of redo generated for "' || 
    23 substr( replace( p_sql, chr(10), ' '), 1, 25 ) || '"...' ); 
    24 end; 
    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 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。

    展开全文
  • OracleUndoRedo通俗理解以下文字...什么是REDOREDO记录transaction logs 分为onlinearchived 以恢复为目的比如 机器停电 那么在重起之后需要online redo logs去恢复系统到失败点比如 磁盘坏了 需要用archived red...
  • Oracleredo和undo

    2015-05-06 15:49:02
    一.REDO 重做日志文件(redo log file)对oracle数据库来说至关重要。它们是数据库的事务日志。oracle维护着两类重做日志文件:在线(online)重做日志文件归档(archived)重做日志文件。这两类重做日志文件都...
  • OracleRedo和Undo

    2014-03-05 09:06:18
    延迟段创建: create table的时候,并没有真正分配段...生成undo信息 修改数据块 给数据块加锁标记,得到锁 生成Redo信息 commit: 为事务生成SCN,计数 LGWR把Redo日志写入到磁盘 -- IO最花时间, PLSQ...
  • ORACLEredo和undo_改变向量

    千次阅读 2015-01-30 13:58:52
    redo和undo 1.1 oracle 9i 任务执行过程 --DML 更新数据操作: 1.创建一个改变向量(保存改变之前的数据)描述undo数据块的改变; 2.创建改变向量(保存改变之后的数据),描述数据块的改变; 3.合并两个改变向量为...
  • insert一条记录时, 表跟undo的信息都会放进 redo , 在commit 或之前, redo 的信息会放进硬盘上. 故障时, redo 便可恢复那些已经commit 了的数据. redo->每次操作都先记录到redo日志,当出现实例故障(像断电...
  • Oracle redo undo 详解

    2020-04-27 15:20:26
    文章目录1 概述2 详解2.1 redo2.2 undo 1 概述 redo undo Record of How to reproduce a change How to undo a change Used of Rolling forward database changes Rollback, read consistency, flashback...
  • redo--> undo-->datafile ...insert一条记录时, 表跟undo的信息都会放进 redo , 在commit 或之前, redo 的信息会放进硬盘上. 故障时, redo 便可恢复那些已经commit 了的数据. redo->每次操作都先记
  • [Oracle] Redo&Undo梳理

    2015-05-15 09:23:00
    Oracle中redo和undo是关键技术的核心, 诸如实例恢复, 介质恢复, DataGuard, 闪回机制等都是给予redo和undo的, 所以很有必要详细梳理这块的知识, 总结记录. 数据变化日志 当我们改变一个数据块时, 都记录了哪些...
  • ORACLEredo和undo_改变向量redo和undo1.1 oracle 9i 任务执行过程--DML 更新数据操作:1.创建一个改变向量(保存改变之前的数据)描述undo数据块的改变;2.创建改变向量(保存改变之后的数据),描述数据块的改变;3...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,505
精华内容 10,202
关键字:

oracle中redo和undo