一 为了更清楚的看出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
te