当对数据进行修改时,Oracle数据库会将旧的数据存储到UNDO表空间(回滚表空间)。回滚表空间让用户可以rollback到修改前的数据,提供了读一致性,并支持闪回查询过去的数据。Undo也用来在Transaction出问题的时候恢复数据,例如用户在执行事务的时候断开会话,没有进行rollback或者commit。或者实例出问题需要shutdown abort的时候,Oracle数据库会恢复数据到用户更改之前的状态。
回滚信息保留到以下条件发生:
- rollback
- commit
- DDL(因为DDL会先Commit)
- 用户不正常的断开会话(自动rollback到用户更改之前的数据)
- 用户使用exit正常断开会话(自动commit)
Undo信息的存储
回滚数据保留的数量和保留的时间依赖于数据库的操作量以及初始化参数的设置。
进行数据操作的时候,数据值变化时,旧值就会被复制到UNDO表空间的UNDO段。Undo段是Oracle数据库自动创建用来支持Transaction的,和所有的段一样,Undo段也是由区组成,区由数据块组成。Undo段自动的增长与收缩,不需要认为干预。
Transaction填充undo段中的区,当transaction结束后,空间将会被回收。如果一个区被写满了,Transaction会从段中下一个区获得空间写入数据。当所有的区都被写满了,Transaction会回到段的第一个区开始重写或者再为段申请分配新的区。
Undo段自动创建,Owner是SYS用户。因为Undo是循环使用的,所以一个Undo段至少两个区。
Undo信息保存在Undo表空间,Undo表空间只能存储Undo段。DBCA创建数据库的时候,会自动创建一个small file的UNDO表空间,虽然可以创建Big file的Undo表空间,但如果在高并发的OLTP环境,大量并发的事务会造成对Undo文件头的争抢,Small File可以避免这个问题。
Undo表空间也是永久表空间,它的Extent Management采用的本地管理Locally Managed(相对于数据字典),Auto Extent Allocation(相对于Uniform)。
对比Undo与Redo数据
Undo用来撤销改变,并保证读一致性与闪回操作。Redo用来重现一个改变。Undo数据也写入到Redo日志中。
随着commit, redo数据被写入到redo日志文件中,redo日志文件存储在磁盘上,redo日志文件是多个副本同时存在磁盘上。Redo用来保证数据的一致性。
对比Shared与Local Undo模式
- Shared Undo: 只在CDB$ROOT设置一个Undo表空间,所有的PDB公用。
- Local Undo: 每个PDB有自己的Undo表空间。如果创建PLUGGABLE PDB的时候需要用到HOT CLONE或者NEAR-ZERO DOWN TIME PDB RELOCATION,必须使用LOCAL UNDO表空间。
启用共享UNDO表空间
SQL> STARTUP UPGRADE;
SQL> ALTER DATABASE LOCAL UNDO OFF;
启用本地UNDO表空间
SQL> STARTUP UPGRADE;
SQL> ALTER DATABASE LOCAL UNDO ON;
通过DATABASE_PROPERTIES试图可以查看LOCAL_UNDO_ENABLED的值, FALSE=SHARED UNDO TABLESPACE, TRUE=LOCAL UNDO TABLESPACE。
SQL> select property_name, property_value from database_properties
2 where property_name = 'LOCAL_UNDO_ENABLED';
PROPERTY_NAME PROPERTY_VALUE
-------------------- --------------------
LOCAL_UNDO_ENABLED FALSE
配置Undo
undo信息的三种状态
- Active 没有提交的undo信息。这些信息永远不会覆写。
- Unexpired 已经提交的undo信息,对于事务来说不再需要,但仍在retention interval内进行保留。如果没有Retention Guarantee,在UNDO表空间没有空间可用时的时候会被覆写。
- Expired 已经提交并以超出retention interval的undo信息,会被active的undo信息覆写。
系统初始化参数UNDO_RETENTION(单位:秒)设置了在COMMIT之后的多少秒内保留Undo数据。
开启了AUTO-EXTENDING的UNDO表空间,这个值是UNDO信息的最短保留时间,也是最长的闪回操作时间。因为开启了AUTO-EXTENDING的UNDO表空间可能会自动重写已经提交但还没有过期的Undo信息,他可能会降低闪回操作能够回退的时间点。
为了避免没有过期的undo信息被重写从而影响闪回,可以设置保证回滚信息的保留期限Guarantee Undo Retention。
RETENTION GUARANTEE是表空间的属性,需要使用ALTER TABLESPACE <tbs name> RETENTION GUARANTEE | NOGUARANTEE
来设置。
启用RETENTION GUARANTEE
SQL> ALTER TABLESPACE undotbs1 RETENTION GUARANTEE;
Tablespace altered.
禁用RETENTION GUARANTEE
SQL> ALTER TABLESPACE undotbs1 RETENTION NOGUARANTEE;
Tablespace altered.
RETENTION GUARANTEE只能设置在UNDO表空间,如果应用到其他表空间,命令执行会报错。
SQL> ALTER TABLESPACE users RETENTION GUARANTEE;
ALTER TABLESPACE users RETENTION GUARANTEE
*
ERROR at line 1:
ORA-30044: 'Retention' can only specified for undo tablespace
临时Undo
临时表也有undo信息,临时表的更改很频繁,将undo存在临时表中可以提升性能,主要是因为临时表空间中的更改不进行redo log的写入。
Temporary Undo的好处
- 减少Undo表空间的使用量。
- 减少到redo log的写入。
- 使Oracle Active Data Guard的物理备用服务器可以在临时表空间进行DML。