UNDO表空间和TEMP空间类似,都是循环使用的,其使用原理大致如下:
当我们使用AUM(自动UNDO管理),并设置了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;如果再不够用,则报空间不足的错误消息。
对于UNDO空间多大合适,有一个计算方法:
每秒平均(或最大)产生的UNDO数据块的数量*块尺寸*UNDO数据保存的最短时间(或最长的SQL运行时间)
其中“每秒平均(或最大)产生的UNDO数据块的数量”可以通过v$undostat字典视图来计算,计算方法如下:
每秒平均产生的UNDO数据块的数量:
SELECT (SUM(undoblks))/ SUM((end_time - begin_time) * 86400) FROM v$undostat;
每秒最大产生的UNDO数据块的数量:
SELECT max(undoblks / ((end_time - begin_time) * 24 * 3600)) FROM v$undostat;
其中“块尺寸”可以通过系统参数db_block_size查询得知(一般默认为8192)。
show parameter db_block_size
其中“UNDO数据保存的最短时间”可以通过系统参数undo_retention查询得知 (默认为900秒)
show parameter undo_retention
而“最长的SQL运行时间”可以通过以下方法确定:
SELECT max(SUM(elapsed_seconds)) FROM v$session_longops GROUP BY sid,serial#,sql_id
将以上得出的数字代入公式,就可以计算出UNDO所需空间的大小了。
例如,我们得出
每秒平均产生的UNDO数据块数量为100,每秒最大产生的UNDO数据块的数量为200;
块尺寸为8192;
undo数据保存的最短时间为900秒,最长的SQL运行时间为2400秒。
则以“每秒平均产生的UNDO数据块的数量*块尺寸*UNDO数据保存的最短时间”来计算,得出
100块/秒*8192字节/块*900秒=737280000字节,约等于703M。
若以“每秒最大产生的UNDO数据块的数量*块尺寸*最长的SQL运行时间”来计算,得出
200块/秒*8192字节/块*2400秒=3932160000字节,约等于3750M。
因此,若将UNDO空间大小设置为703M,则可以基本保证在900秒前发生的改变,是可以查到的,或者说,在对于一个运行时间不超过900秒的SQL语句来说,是不太会遭遇“ORA-01555 快照过旧”这种错误的。
而若将UNDO空间大小设置为3750M,则可以基本保证在2400秒(样例系统中可以查到的SQL最长运行时间)前发生的改变,是可以查到的,或者说,在对于一个运行时间不超过2400秒的SQL语句来说,是不太会遭遇“ORA-01555 快照过旧”这种错误的。
参考:
http://book.51cto.com/art/200806/75648.htm