Oracle Undo 原理
从9i开始,Oracle还提供了一种新的撤销数据(Undo Data)管理方式,就是使用Oracle自动管理的撤销(Undo)表空间(Automatic Undo Management,通常被缩写为AUM)。
(1)检查empno=7788记录在Buffer Cache中是否存在,如果不存在则读取到Buffer Cahce中;
(2)在回滚表空间的相应回滚段事务表上分配事务槽,这个操作需要记录Redo信息;
(3)从回滚段读入或都在Buffer Cache中创建sal = 3000的前镜像,这需要产生Redo信息并记入Redo Log Buffer;
(4)修改Sal = 4000,这是update的数据变更,需要记入Redo Log Buffer;
(5)当用户提交时,会在Redo Log Buffer记录提交信息,并在回滚段标记该事务为非激活(INACTIVE)。
如果用户回滚(Rollback)事务,则Oracle需要从回滚空间中把前镜像数据读取出来,修改数据缓冲区,完成回滚,这个过程本身也要产生Redo,所以回退这个操作是很昂贵的。
在性能优化中,有一个性能指标称为平均事务回滚率(Rollback per Transaction),用来衡量数据库的提交与回滚效率。
对于insert操作,回滚段只需要记录插入记录的rowid,如果回退,只需将该记录根据rowid删除即可;对于update操作,回滚段只需要记录被更新字段的旧值即可(前镜像),回退时通过旧值即可(前镜像),回退时通过旧值覆盖新值即可完成回滚;对于delete操作,Oracle则必须记录整行的数据,在回滚时,Oracle通过一个反向操作恢复删除的数据。
对于相同数据量的数据操作,通常insert产生最少的Undo,update产生的Undo居中,而delete操作产生的Undo最多。 这也就是我们经常看到的,当一个大的Delete操作失败或都回滚,总是需要很长的时间,并且会有大量的Redo生成。
回滚段在Undo表空间分配,其数据在Buffer Cache内存中的管理方式与用户数据一致,同样按照相同的规则写出到Undo表空间的数据文件上。Undo表空间中的存储空间同样按照Segment来分配和使用。回滚段的作用除了回退事务外,还要参与事务恢复,以及提供读一致性。
并发控制和一致性读
一方面Oracle通过锁定机制实现数据库的并发控制,别一方面通过多版本(Multi-versioning Model)模型来进行并发数据访问。
通过多版本架构,Oracle实现了读取和写入的分离,使用得写入不阻塞读取;读取不阻塞修改。这是Oracle数据库区别于其他数据库的一个重要特征。多版本模型在Oracle数据中是通过一致性读来实现的,一致性读也正是回滚表空间的主要作用之一。
回滚段的前世今生
在Oracle 9i之前,回滚表空间创建之后,Oracle随后创建回滚段供数据库使用,
可以通过如下命令指定使用特定的回滚段:
set transaction use rollback segment <rollback_segment_name>;
在11g中Undo段的命名规则有了进一步变化,现在将回滚段的创建时间戳包含在回滚段名称中。
SYS@ orcl> select segment_name, tablespace_name, status from dba_rollback_segs;
SEGMENT_NAME TABLESPACE_NAME STATUS
------------------------- ------------------------------ ----------------
SYSTEM SYSTEM ONLINE
_SYSSMU10_4131489474$ UNDOTBS1 ONLINE
_SYSSMU9_1735643689$ UNDOTBS1 ONLINE
_SYSSMU8_3901294357$ UNDOTBS1 ONLINE
_SYSSMU7_3517345427$ UNDOTBS1 ONLINE
_SYSSMU6_2897970769$ UNDOTBS1 ONLINE
_SYSSMU5_538557934$ UNDOTBS1 ONLINE
_SYSSMU4_1003442803$ UNDOTBS1 ONLINE
_SYSSMU3_1204390606$ UNDOTBS1 ONLINE
_SYSSMU2_967517682$ UNDOTBS1 ONLINE
_SYSSMU1_592353410$ UNDOTBS1 ONLINE
从Oracle 9i开始,Oracle引入了自动管理的Undo表空间,如果选择使用自动的Undo表空间管理,那么用户不再能够创建或删除回滚段,也不再需要为事务指写回滚段,这一切由Oracle自动进行。
SYS@ orcl> show parameter undo
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string AUTO
undo_retention integer 900
undo_tablespace string undotbs1
在自动管理的Undo表空间下,回滚段的个数是Oracle根据数据库的繁忙程度自动分配或都回收的,数据库创建时缺省初始化10个回滚段。
SYS@ orcl> select * from v$rollname;
USN NAME
---------- ------------------------------
0 SYSTEM
1 _SYSSMU1_592353410$
2 _SYSSMU2_967517682$
3 _SYSSMU3_1204390606$
4 _SYSSMU4_1003442803$
5 _SYSSMU5_538557934$
6 _SYSSMU6_2897970769$
7 _SYSSMU7_3517345427$
8 _SYSSMU8_3901294357$
9 _SYSSMU9_1735643689$
10 _SYSSMU10_4131489474$
在系统繁忙时,可以从数据库的告警日志文件中看到回滚段的动态创建和释放过程
Created Undo Segment _SYSSMU11$
SMON offlining US=11
## 原有Undo表空间的回滚段会逐渐离线,新的表空间Undo段顺序创建
SQL> crreate undo tablespace undotbs2 datafile size 500M
SQL> alter system set undo_tablespace='UNDOTBS2';
Oracle 10g的UNDO_RETENTION管理增强
在AUM模式下,UNDO_RETENTION,默认是一个NO Guaranteed的限制。
从Oracle 10g开始,如果设置undo_retention为0,那么Oracle启用自动调整以满足最长运行查询的需要。
这个特性的引入伴随着几个新的隐含初始化参数:
SYS@ orcl> @GetHidPar
Enter value for par: undo_autotune
NAME VALUE PDESC
------------------------------ --------------- --------------------------------------------------
_undo_autotune TRUE enable auto tuning of undo_retention
SYS@ orcl> @GetHidPar
Enter value for par: collect_undo_stats
NAME VALUE PDESC
------------------------------ --------------- --------------------------------------------------
_collect_undo_stats TRUE Collect Statistics v$undostat
alter tablespace undotbs1 retention guarantee|noguarantee;
SYS@ orcl> select tablespace_name, contents, retention from dba_tablespaces;
TABLESPACE_NAME CONTENTS RETENTION
------------------------------ --------- -----------
SYSTEM PERMANENT NOT APPLY
SYSAUX PERMANENT NOT APPLY
UNDOTBS1 UNDO NOGUARANTEE
TEMP TEMPORARY NOT APPLY
USERS PERMANENT NOT APPLY
在数据文件autoextend off时,设置guarantee时当空间不足时会出现ORA-30036错误,在noguarantee时不会出现错误,这就是GUARANTEE与NOGUARANTEE的不同。