UNDO数据管理

来源:互联网 发布:手机网购比价软件 编辑:程序博客网 时间:2024/05/23 17:36

本篇介绍的是Oracle数据库中UNDO数据的基本概念


1   基本概念

UNDO数据就是“原始的”,“旧的”,“修改前”的数据。保留这些旧的数据的目的就是为了让数据库能够实现事务的回滚、读一致性、闪回技术等。


UNDO数据都是被保存在UNDO表空间中。当一个事务开始的时候,数据库会为这个事务分配一个UNDO段,这个事务的所产生的UNDO数据都将保持在这个段中(不会保持在其他段中)。并且一个UNDO段可以给多个事务来使用。


2   UNDO数据的状态

UNDO数据并不会永久的存储在UNDO表空间中,随着数据状态的改变,数据库会有选择的进行覆盖,以便节约空间。UNDO数据包括了3个状态:

  • Active当事务没有提交前,UNDO数据都处于Active的状态,并且这些数据“一定不会”被覆盖。
  • Unexpired在事务提交以后,并且还没有超过保留期限,数据就处于Unexpired状态,此时数据可以被覆盖。这个状态下的数据有可能会被“读一致性”、“闪回技术”等使用。通常,这个状态的数据不会被数据库优先选择覆盖,只有在Expired的数据都被覆盖,才考虑覆盖这些数据(可以设置为不能被覆盖,见“3.2  Retention Guarantee(保证保留)”)。
  • Expired在事务提交以后,并且数据超过保留期限,数据就处于Expired状态,此时数据可以被覆盖。通常这个状态下的数据一般就不再需要被使用了。数据库会预先选择覆盖这个状态的数据。
实际,数据库没有智能到能够自动判断出,哪些数据将来可能会被使用,哪些数据将来不需要被使用。所以数据库通过设置一个时间来判断UNDO数据是否需要被使用,超过这个时间,数据库就认为它不需要再被使用了,状态就从Unexpired变成Expired。而这个时间就被称为Undo Retention(保留期限)。可以通过UNDO_RETENTION参数来设置这个保留期限的值。
如果数据库操作需要使用到UNDO数据,而数据已经被覆盖,这时就会报出“snapshot too old”这个错误。要避免这个错误的出现,一般将UNDO_RETENTION参数的值设置为数据库中最长的一个查询的时间。

3   UNDO表空间的管理

你可以在一个数据库中创建多个UNDO表空间,但是有效的表空间只有一个,我们可以通过UNDO_TABLESPACE初始化参数来进行设置。数据库对UNDO表空间的管理默认采用的是自动管理(Automatic Undo Management, AUM),这个可以通过UNDO_MANAGEMENT参数来进行设置(默认值为TRUE)。

3.1  AUM

在AUM中最主要的特性就是:数据库会自动调优UNDO的保留期限(这个特性可以通过隐藏参数来控制:_undo_retention=true)。数据库会根据UNDO表空间的大小和系统的活动情况来自动调优UNDO保留期限为一个合适的值。默认:数据库会每10分钟收集一次并计算这个保留期限的实际值。这个值我们可以通过V$UNDOSTAT视图来查看。

SQL> select tuned_undoretention from v$undostat;TUNED_UNDORETENTION-------------------                900


但是UNDO表空间的设置,也直接影响了Undo Retention,如果UNDO表空间大小是:

  • 自动扩展,数据库一定会保留UNDO_RETENTION参数指定的时间(保留期限的实际值=UNDO_RETENTION参数的值)。在这种情况下,容易引起UNDO表空间的急剧增大。
  • 固定大小,数据库会自动调优保留期限的值(会忽略UNDO_RETENTION参数的值,实际值=max(最长查询的时间+300s,UNDO_RETENTION参数))。这个只有在UNDO表空间没有启用retention guarantee的特性时,才有效。

3.2  Retention Guarantee(保证保留)

只要启用了UNDO表空间的Retention Guarantee特性,就能让UNDO数据一定保留UNDO_RETENTION参数设置的时间。在这个时间没有到之前,将不会被允许覆盖。

SQL> alter tablespace undotbs1 retention guarantee;Tablespace altered.


3.3  UNDO表空间的空间分配

如果没有启用Retention Guarantee的特性,空间分配方式如下:

  1. 会寻找不含有Active的状态数据的段。如果没有找到,就创建一个新的回滚段;否则就使用找到的回滚段。
  2. 但是如果段中空闲的空间不够大,不足以来存储UNDO数据,那么数据库将创建一个新的区。
  3. 如果不能创建新的区(通常就是表空间大小不可扩展的情况下),它会重用已使用的区(也就是覆盖之前的数据)
    • 尝试使用自己段中的Expired的区
    • 尝试偷取其它段中的Expired的区
    • 尝试使用自己段中的Unexpired的区
    • 尝试偷取其它段中的Unexpired的区
    • 报告一个错误

4   UNDO表空间的监控

4.1  使用V$UNDOSTAT视图

需要关注这个视图的几个字段:

  • undotsn:最近一个活动的UNDO表空间号
  • undoblks:消耗的UNDO块总数量
  • maxquerylen:最大的查询时间(s)
  • unxpstealcnt:偷未过期区的次数
  • unxpblkrelcnt:移除未过期块的数量
  • unxpblkreucnt:重用未过期块的数量
以上3个字段如果不为0,通常都是由于空间太小,或者没有启用Retention Guarantee特性引起的
  • nospaceerrcnt:空间不足错误发生的次数
  • ssolderrcnt:snapshot too old错误发生的次数
  • activeblks:活动块的数量
  • unexpiredblks:未过期块的数量
  • expiredblks:过期块的数量

4.2  UNDO表空间大小的设置
在一个系统新上线的情况下,最好打开UNDO表空间的自动扩展(无最大值),持续观察一段时间;当业务稳定以后,UNDO表空间的已使用大小通常稳定在一个范围中(假设大小在400M左右),这个时候就可以关闭自动扩展,将表空间设置为固定大小(大小为400M往上浮动10%,也就是400*1.1=440M)。
观察已使用的UNDO的大小,可以用下面这个SQL语句
SQL> select sum(rssize/1024/1024) USED_MB  2  from v$rollstat r join dba_rollback_segs s  3  on r.usn = s.segment_id  4  where s.tablespace_name='UNDOTBS1';   USED_MB---------- 22.109375

除此之外,也可以用“UNDO顾问”来完成表空间大小的设置。


0 0
原创粉丝点击