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