作者:dbtan |【转载时请以超链接形式标明文章出处作者信息】


什么是回滚和撤销:

首先来介绍一下什么是回滚和撤销。我们知道,从Oracle 6版本到Oracle 9i版本,Oracle用数据库中的回滚段(Rollback)来提供撤销数据(Undo Data);而从Oracle 9i开始,Oracle还提供了一种新的撤销数据(Undo Data)管理方式,就是使用Oracle自动管理的撤销(Undo)表空间(Automatic Undo Management,通常被缩写为AUM)。

事务使用回滚段来记录变化前的数据或者撤销信息,假定发出了一个更新语句:

update emp set sal=4000 where empno=7788;

下面看一下这个语句是怎样执行的(为了叙述方便,这里尽量简化了情况):

⑴ 检查empno=7788记录在Buffer Cache中是否存在,如果不存在则读取到Buffer Cache中;
⑵ 在回滚表空间的相应回滚段事务表上分配事务槽,这个操作需要记录Redo信息;
⑶ 从回滚段读入或者在Buffer Cache中创建sal=3000的前镜像,这需要产生Redo信息并记入Redo Log Buffer;
⑷ 修改sal=4000,这是update的数据变更,需要记入Redo Log Buffer;
⑸ 当用户提交时,会在Redo Log Buffer记录提交信息,并在回滚段标记事务为非激活(INACTIVE)。

在以上事务处理过程中,注意Redo和Undo是交替出现的,这两者对于数据库来说都非常重要。在以上步骤中,对于回滚段的操作存在多处,在事务开始时,首先需要在回滚表空间获得一个事务槽,分配空间,然后创建前镜像,此后事务的修改才能进行,Oracle必须以此来保证事务是可以回滚的

如果用户提交(commit)了事务,Oracle会在日志文件记录提交,并且写出日志,同时会在回滚段中把该事务标记为已提交,提交事务在回滚段事务表的状态为INACTIVE,然后该事务所使用的回滚空间可以被重用,回滚段空间是循环使用的;如果用户回滚(Rollback)事务,则Oracle需要从回滚段中把前镜像数据读取出来,修改数据缓冲区,完成回滚,这个过程本身也要产生Redo,所以回退这个操作是很昂贵的。

在Oracle的性能优化中,有一个性能指标称为平均事务回滚率(Rollback per Transaction),用来衡量数据库的提交与回滚效率。
Statspack中计算Rollback per transaction的公式为:

Round(User rollbacks/(user commits + user rollbacks),4)×100%

其中user commitsuser rollbacks数据来自系统的统计信息,可以从v$sysstat视图中得到,在Statspack中也包含着部分数据的输出:

Statistic                                      Total     per Second    per Trans
--------------------------------- ------------------ -------------- ------------
user commits                                     508            0.2          1.0
user rollbacks                                     8            0.0          0.0

这个指标应该接近于0,如果该指标过高,则说明数据库的回滚过多。回滚过多不仅说明数据库经历了太多的无效操作,而且这些操作会极大影响数据库性能。

- The End -