首页 > 代码库 > Oracle 中UNDO与REDO的差别具体解释

Oracle 中UNDO与REDO的差别具体解释

一 为了更清楚的看出2者差别,请看下表:


                                              UNDO                                                                   REDO
Record of How to undo a change How to reproduce a change
Used for Rollback, Read-Consistency Rolling forward DB Changes
Stored in Undo segments Redo log files
Protect Against    Inconsistent reads in multiuser systems    Data loss

简单看来,UNDO主要记录怎样撤销事务和保证读一致性;REDO则是负责数据库前滚(重做)。保护数据不丢失。

 二 以下我们来通过实例说明undo 和 redo的关系:

1 我们将证明下面事实:

- oracle 中redo包括undo;

- checkpoint 会导致脏数据写入datafile;

- buffers 会被写入当前的undo 表空间


2 操作步骤:

- 创建1个undo表空间:undotbs2
- 创建1个表空间:test_undo
- 在表空间test_undo创建表:test_undo_tab (txt char(1000))
- 向表test_undo_tab插入2条记录txt – teststring1, teststring2。运行手工checkpoint操作
- 手工日志切换、切换undo 表空间
- 更新teststring1为teststring_uncommitted而且不提交
- 新开一个session 更新 teststring2为teststring_uncommitted而且提交
- 检查update前后的值都被记录在当前redo log中
- 检查undo 表空间不包括更新之前的值
- 进行手工checkpoint,这样undo信息将被写入磁盘
- 检查undo 表空间包括更新前的值

3 详细实现:

 - 查找当前undo表空间

SQL> show parameter undo_tablespace


NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
undo_tablespace                      string      UNDOTBS1

- 创建Undo表空间 undotbs2:

SQL> create undo tablespace undotbs2 datafile ‘/u01/app/oracle/undotbs2.dbf‘
  2  size 100m;

Tablespace created.

- 创建表空间 test_undo
SQL> create tablespace test_undo datafile ‘/u01/app/oracle/test_undo.dbf‘
  2  size 128k;

Tablespace created.


- 创建測试表 test_undo_tab:

SQL> create table test_undo_tab(txt char(1000)) tablespace test_undo;

Table created.

SQL> insert into test_undo_tab values (‘teststring1‘);

1 row created.

SQL> insert into test_undo_tab values (‘teststring2‘);

1 row created.

SQL> commit;

- 运行手工检查点。将以上改变写入数据文件:

SQL> alter system checkpoint;

System altered.

- 设置undotbs2为当前undo表空间:

SQL> alter system set undo_tablespace=undotbs2;

System altered.

SQL> show parameter undo_tablespace;

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
undo_tablespace                      string      UNDOTBS2

- 进行日志切换使当前日志不包括字符串teststring

SQL> alter system switch logfile;


System altered.


- 查找当前日志

SQL> col member for a30
SQL> select member, l.status from v$log l, v$logfile f
  2  where l.group# = f.group#
  3  and l.status = ‘CURRENT‘;

MEMBER                         STATUS
------------------------------ ----------------
/u01/app/oracle/oradata/orcl/r CURRENT
edo02.log


- 更新測试表中一行而且不提交

SQL> update test_undo_tab set txt = ‘teststring_uncommitted‘
  2  where txt = ‘teststring1‘;

1 row updated.

- 新开一个session 更新另外一行而且提交

SQL>  update test_undo_tab set txt = ‘teststring_committed‘
      where txt = ‘teststring2‘;
      commit;


- 查看这时候的redo log应该包括redo 和 undo (提交的和未提交的数据信息)

[oracle@dylan ~]$  strings /u01/app/oracle/oradata/orcl/redo02.log | grep teststring
teststring_uncommitted                                                                                  
teststring1                                                          

teststring_committed                                                 

teststring2
- 检查当前数据文件应该是不包括更新后的数值(仅仅有更新前数据)由于还未触发检查点

[oracle@dylan ~]$ strings /u01/app/oracle/test_undo.dbf | grep teststring

teststring2                                                                  
teststring1


- 此时触发检查点

SQL> alter system checkpoint;

- 再次检查数据文件发现数据已为最新值(提交的和未提交的值)

[oracle@dylan ~$ strings /u01/app/oracle/test_undo.dbf|grep teststring

teststring_committed                                                                                                               ,
teststring_uncommitted



- 最后检查Undotbs2表空间发现包括更新前的数值
[oracle@dylan ~]$ strings /u01/app/oracle/undotbs2.dbf | grep teststring

teststring2                                                                  
teststring1

- 清理创建的对象
SQL>drop tablespace test_undo including contents and datafiles;
    alter system set undo_tablespace=undotbs1;
    drop tablespace undotbs2 including contents and datafiles;


三 进一步探讨:


Let’s see what will happen if undo is stored in redo logs only.

假设仅将undo信息存储于redo logs会怎么样?

A redo log can be reused once changes protected by it have been written to datafiles (and archivelogs if database is in archivelog mode).

It implies that if I make a change and do not commit it 
- Change is written to a redo log  假设我改变的数据而没提交。此时改变将记录到redo log
- checkpoint takes place  检查点发生
- uncommitted change is written to datafile  后未提交的数据写入了数据文件
- I decide to rollback the change  这时我打算回滚
- If redo log has not been overwritten  假设redo log没被覆盖
. search entire redo log for the undo and then rollback  那么搜素整个redo log进行回滚操作
else (redo log has been overwritten)
. undo information is not available for rollback.    否则将无法回滚,undo信息已丢失!

One might argue that if somehow a redo log is not allowed to be overwritten until it contains active undo, we might be able to manage with undo stored in redo logs only. This solution is not feasible as
- size of redo logs will grow enormously large very soon as thet contain both undo and redo (a user might decide not to end a transaction for months)
- to rollback a change, enormous amount of data in redo logs (both redo and undo) will have to be searched leading to degraded performance
- there will be contention on redo logs as they are being used for both
. writing redo and undo
. reading to rollback a change 

有人或许会争论:那就不同意redo log 覆盖undo 信息直到包括新的undo,这样redo log将变得异常大从而影响系统性能!

Hence, undo information has to be stored separately from redo and is used for rolling back uncommited transactions . The undo stored in undo buffers/undo tablespace is additionally used for
- read consistency   读一致性
- flashback query      闪回查询
- flashback version query   闪回版本号查询







Reference: http://oracleinaction.com/undo-and-redo-in-oracle/
                                   http://oraclenz.wordpress.com/2008/06/22/differences-between-undo-and-redo/









---------------------------------------
Dylan    Presents.

Oracle 中UNDO与REDO的差别具体解释