要配置AUM,我们先要设置初始化参数undo_management。该参数用来说明undo的管理方式,它有两个取值。
auto:表示采用AUM来管理undo。
manual:表示采用MUM来管理undo,这也就意味着我们要手工创建rollback segment等。
在AUM下,我们只需要创建undo表空间(可以使用前面描述的使用Database Control的图形界面来创建undo表空间,也可以使用SQL命令),并指定初始化参 数undo_tablespace,该参数说明数据库当前使用哪个undo表空间。剩下的工作,包括undo segment的创建、扩展、收缩、删除等,都由数据库自动完成,如 下所示:
SQL> show parameter undo_management
NAME TYPE VALUE
----------------- ----------- -------------
undo_management string AUTO
SQL> create undo tablespace undonew datafile '/u01/app/
oracle/oradata/ora10g/undonew01. dbf' size 10M autoextend on;
SQL> alter system set undo_tablespace=undonew;
如果我们指定了undo_management为auto,但是在设定undo_tablespace时,指定了某个不存在的undo表空间,则实例启动时报错;如果没有设定 undo_tablespace,则系统会查找第一个可用的undo表空间;如果没有找到可用的undo表空间,则使用位于系统表空间里的rollback segment,这样非常不好 ,增加了系统表空间的压力。
当发生一个DML操作时,服务器进程会选择一个undo segment。AUM采用的是事务绑定undo segment的算法。该算法说明如下。
首先尝试将每个undo segment绑定一个事务,也就是每个undo segment上只被一个事务使用。
如果不能发现完全空闲的(也就是没有与任何事务绑定)undo segment,则系统会尝试将其他脱机的undo segment联机。
如果没有可用的undo segment进行联机,则会尝试创建一个新的undo segment。
如果上面的步骤都没有成功,比如由于没有可用空间了,而不能创建新的undo segment,则事务绑定算法会去尝试找最早被使用的那个undo segment。这种 情况下,不同的多个事务才会在一个相同的undo segment里同时运行。
既然存在undo segment的扩张,就存在undo segment的收缩。收缩由SMON完成,在下面的情况下会收缩undo segments:
每隔12个小时会收缩一次,删除那些idle状态的extents;
当前台进程进行DML而需要undo时,发现空间不够用,则会唤醒SMON进行一次收缩。也就是说,将其他undo segment里暂时没被使用的extent拿过来用。
从前面的描述中,我们已经知道,当Oracle在提供一致性读的过程中,会根据ITL槽里记录的undo块的地址,而搜索所有相关联的undo块。只要使用undo块的 事务提交或者回滚,则这些undo块就不再被事务所需要;也就是说,其中包含的旧的数据可以被覆盖。这样就会发生在查找改变前的旧值的过程中,找不到 足够旧的值,而抛出ORA-1555的错误消息。为此,Oracle为undo的管理提供了另一个参数:undo_retention。该参数以秒为单位,表示当事务提交或回滚以 后,该事务所使用的undo块里的数据需要保留多长时间;当保留的时间超过undo_retention所指定的时间以后,该undo块才能够被其他事务覆盖。
当我们使用AUM,并设置了undo_retention以后,undo块就存在四种状态。
Active:表示正在使用该undo的事务还没有提交或回滚。
Inactive:表示该undo上没有活动的事务,该状态的undo可以被其他事务覆盖。
Expired:表示该undo持续inactive的时间超过undo_retention所指定的时间。
Freed:表示该undo块内容是空的,从来没有被使用过。
当活动的事务使用undo segment时,在AUM模式下,事务可以在不同的undo segment之间动态交换undo空间,也就是在不同的undo segment里交换extents。 当一个正在执行的事务需要更多的undo空间时,首先会重用当前undo segment里的可用空间;如果当前undo segment里的可用空间(也就是extents)不足时 ,则会按照下面的步聚获得所需要的extent:
获取undo表空间里可用的、空的extents;
获取其他undo segment里的expired状态的extents;
如果undo表空间里的数据文件启用了自动扩展(autoextend on),则数据文件进行自动扩展;
如果undo表空间里的数据文件没有启用自动扩展,则获取其他undo segment里的INACTIVE状态的extents;
如果以上步骤均无法获得可用空间时,报空间不足的错误消息。
这种动态的方式使得空间的使用最为高效。我们来举例说明,如图7-2所示。
图7-2 undo获取可用空间的机制
在图7-2中,假设undo表空间中总共存在5个undo segment(US1、US2、US3、US4和US5)。每个undo segment中包含7个extent,其中每个extent的状态采用A 、I、X和F来表示。那么当使用US5的事务还需要额外的可用空间时,首先会使用US5中两个状态为F的extents;如果不够用,则使用US4中的3个状态为F的 extents;如果还不够用,则使用US3中的3个状态为X的extents;如果仍然不够用,则使用US1中的3个状态为I的extents;如果再不够用,则报空间不足的错 误消息。
从这里可以看出,在AUM里,分配undo块的算法不仅有效,而且会尽可能地将INACTIVE状态的extents保留足够长的时间。在Oracle 10g里,如果undo表空间 有足够的可用空间,则Oracle会将undo信息保留的时间与当前运行时间最长的那个查询所需要的时间相同。
默认情况下,Oracle 10g会每隔30秒钟就收集统计信息来自动调整undo retention,收集的信息包括运行时间最长的查询、产生undo的速度等。我们可以通 过设置undo_retention参数来改变这种自动的调整。该参数的默认值为900秒。如果我们没有为该参数指定值,或指定了0,则Oracle会自动调整undo retention,并以900秒作为最低值。否则,使用我们设置的该值作为undo保留的时间。
如果设置undo_retention为0,则实例会获取运行时间最长的那个查询所需要的时间,比如为N秒,然后将undo信息保留N秒。当undo表空间的尺寸太小,而不 能保留这个最长的时间时,则会尽可能地利用现有的可用空间来让undo保留的时间尽可能长,并不会立刻扩展undo数据文件。除非要覆盖的undo信息是在距 今900秒以内发生的,才会去扩展数据文件。