Oracle数据库中最重要的两部分数据:redo与undo。redo(重做信息)是oracle 在线(或归档)重做日志文件中记录的信息,万一出现失效时可以利用这些数据来“重放”(或重做)事务。
undo(撤销信息)是Oracle在undo段中记录的信息,用于取消或回滚事务。
重做日志文件(redo log file)对Oracle数据库来说至关重要。Oracle维护着两类重做日志文件:
在线(online)重做日志文件和归档(archived)重做日志文件。 都用于恢复。
其主要目的是:万一实例失效或者介质失败,它们就能派上用场。
归档重做日志文件实际上就是已填满的”旧“在线重做日志文件的副本。
对数据库执行修改时,数据库会生成undo信息。以便回到更改前的状态。
redo用于在失败时重放事务(恢复事务),undo则用于取消一条语句或一组语句的作用。
与redo不同,undo在数据库内部存储在一组特殊的段中,这称为undo段(undo segment)
怎么才能看到undo生成(undo generation)的具体情况呢?
(1)创建一个空表
(2)对它做一个全表扫描,观察读表所执行的I/O数量。
(3)在表中填入许多行(但没有提交)
(4)回滚这个工作、并撤销。
(5)再次进行全表扫描,观察所执行的I/O数量。
- scott@orclpdb1:orclcdb> create table t
- 2 as
- 3 select *
- 4 from all_objects
- 5 where 1=0;
-
- Table created.
-
- scott@orclpdb1:orclcdb> set autotrace on
- scott@orclpdb1:orclcdb> select * from t;
-
- no rows selected
-
-
- Execution Plan
- ----------------------------------------------------------
- Plan hash value: 1601196873
-
- --------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- --------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | 481 | 2 (0)| 00:00:01 |
- | 1 | TABLE ACCESS FULL| T | 1 | 481 | 2 (0)| 00:00:01 |
- --------------------------------------------------------------------------
-
-
- Statistics
- ----------------------------------------------------------
- 96 recursive calls
- 181 db block gets
- 148 consistent gets
- 1 physical reads
- 30504 redo size
- 2375 bytes sent via SQL*Net to client
- 366 bytes received via SQL*Net from client
- 1 SQL*Net roundtrips to/from client
- 2 sorts (memory)
- 0 sorts (disk)
- 0 rows processed
-
- scott@orclpdb1:orclcdb> set autotrace traceonly statistics
- scott@orclpdb1:orclcdb> select * from t;
-
- no rows selected
-
-
- Statistics
- ----------------------------------------------------------
- 0 recursive calls
- 0 db block gets
- 0 consistent gets
- 0 physical reads
- 0 redo size
- 2375 bytes sent via SQL*Net to client
- 366 bytes received via SQL*Net from client
- 1 SQL*Net roundtrips to/from client
- 0 sorts (memory)
- 0 sorts (disk)
- 0 rows processed
-
- scott@orclpdb1:orclcdb>
- scott@orclpdb1:orclcdb> insert into t select * from all_objects;
-
- 54936 rows created.
-
-
- Statistics
- ----------------------------------------------------------
- 1377 recursive calls
- 9467 db block gets
- 105040 consistent gets
- 304 physical reads
- 9009588 redo size
- 494 bytes sent via SQL*Net to client
- 937 bytes received via SQL*Net from client
- 2 SQL*Net roundtrips to/from client
- 31 sorts (memory)
- 0 sorts (disk)
- 54936 rows processed
-
- scott@orclpdb1:orclcdb> rollback;
-
- Rollback complete.
-
- scott@orclpdb1:orclcdb> select * from t;
-
- no rows selected
-
-
- Statistics
- ----------------------------------------------------------
- 2 recursive calls
- 1 db block gets
- 1134 consistent gets
- 0 physical reads
- 140 redo size
- 2375 bytes sent via SQL*Net to client
- 370 bytes received via SQL*Net from client
- 1 SQL*Net roundtrips to/from client
- 0 sorts (memory)
- 0 sorts (disk)
- 0 rows processed
-
- scott@orclpdb1:orclcdb> set autotrace traceonly statistics
- scott@orclpdb1:orclcdb> select * from t;
-
- no rows selected
-
-
- Statistics
- ----------------------------------------------------------
- 0 recursive calls
- 0 db block gets
- 1118 consistent gets
- 0 physical reads
- 0 redo size
- 2375 bytes sent via SQL*Net to client
- 370 bytes received via SQL*Net from client
- 1 SQL*Net roundtrips to/from client
- 0 sorts (memory)
- 0 sorts (disk)
- 0 rows processed
-
- scott@orclpdb1:orclcdb>
- scott@orclpdb1:orclcdb>
- scott@orclpdb1:orclcdb> create table t (x int)
- 2 ;
- create table t (x int)
- *
- ERROR at line 1:
- ORA-00955: name is already used by an existing object
-
-
- scott@orclpdb1:orclcdb> drop table t;
-
- Table dropped.
-
- scott@orclpdb1:orclcdb> create table t(x int);
-
- Table created.
-
- scott@orclpdb1:orclcdb> select extent_id, bytes, blocks
- 2 from user_extents
- 3 where segment_name='T'
- 4 order by extend_id;
- order by extend_id
- *
- ERROR at line 4:
- ORA-00904: "EXTEND_ID": invalid identifier
-
-
- scott@orclpdb1:orclcdb> select extent_id, bytes, blocks
- 2 from user_extents
- 3 where segment_name='T'
- 4 order by extent_id;
-
- no rows selected
-
-
- Statistics
- ----------------------------------------------------------
- 252 recursive calls
- 0 db block gets
- 497 consistent gets
- 6 physical reads
- 0 redo size
- 504 bytes sent via SQL*Net to client
- 446 bytes received via SQL*Net from client
- 1 SQL*Net roundtrips to/from client
- 14 sorts (memory)
- 0 sorts (disk)
- 0 rows processed
-
- scott@orclpdb1:orclcdb> insert into t(x) values (1);
-
- 1 row created.
-
-
- Statistics
- ----------------------------------------------------------
- 39 recursive calls
- 62 db block gets
- 35 consistent gets
- 1 physical reads
- 6536 redo size
- 494 bytes sent via SQL*Net to client
- 925 bytes received via SQL*Net from client
- 2 SQL*Net roundtrips to/from client
- 1 sorts (memory)
- 0 sorts (disk)
- 1 rows processed
-
- scott@orclpdb1:orclcdb> rollback;
-
- Rollback complete.
-
- scott@orclpdb1:orclcdb> select extent_id, bytes, blocks
- 2 from user_extents
- 3 where segment_name='T'
- 4 order by extent_id;
-
- 1 row selected.
-
-
- Statistics
- ----------------------------------------------------------
- 1 recursive calls
- 0 db block gets
- 135 consistent gets
- 0 physical reads
- 0 redo size
- 709 bytes sent via SQL*Net to client
- 457 bytes received via SQL*Net from client
- 2 SQL*Net roundtrips to/from client
- 1 sorts (memory)
- 0 sorts (disk)
- 1 rows processed
-
- scott@orclpdb1:orclcdb> set trace off
- SP2-0158: unknown SET option "trace"
- scott@orclpdb1:orclcdb> set autotrace off
- scott@orclpdb1:orclcdb> select extent_id, bytes, blocks
- 2 from user_extents
- 3 where segment_name='T'
- 4 order by extent_id;
-
- EXTENT_ID BYTES BLOCKS
- ---------- ---------- ----------
- 0 65536 8
-
- 1 row selected.
-
- scott@orclpdb1:orclcdb>
可以看到,表创建之后没有分配任何存储空间——这个表没有使用任何区段。完成一个INSERT 后,紧接着执行ROLLBACK,可以看到INSERT分配了存储空间,不过ROLLBACK并没有将分配的存储空间”释放“。
总结:
尽管undo信息存储在undo表空间或undo段中,但也会受到redo的保护。
意思是,会把undo数据当成是表数据或索引数据已有,对undo的修改会生成一些redo,这些redo将计入日志。将undo数据增加到undo段中,并像其他部分的数据一样,在缓冲区中得到缓存。
提交和回滚处理
COMMIT做什么
Rollback做什么
生成的redo越多,操作花费的时间就越长,整个系统也会越慢。
不能,因为重做日志对数据库至关重要,它不是开销,不是浪费。重做日志是实实在在必不可少的。是数据库采用的工作方式。 如果你关闭了redo,那么磁盘驱动器的任何暂时失败,掉电或某个软件崩溃都会导致整个数据库不可用。而且不可恢复。