UNDO管理之一:UNDO基础

UNDO管理之一:自动UNDO管理

实验版本
Oracle数据库版本:

SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bi
PL/SQL Release 10.2.0.1.0 - Production
CORE    10.2.0.1.0      Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

SQL> 
SQL> ! uname -a
Linux localhost.localdomain 2.6.32-300.10.1.el5uek #1 
SMP Wed Feb 22 17:37:40 EST 2012 x86_64 x86_64 x86_64 GNU/Linux

UNDO基础

UNDO的作用
    UNDO是Oracle中的一个很重要的机制,在对数据库进行修改的时候,Oracle会将数据块上修改之前的数据
(称为前映像,before image)保存在回滚段中,这样当我们需要进行回滚(rollback)的时候就很容易能
从回滚段中将之前的数据取出来将数据块上面的数据还原回来。
当然上面所说的只是UNDO的最基本的一个用途,实际上UNDO的应用远不止于此,下面就列举一下UNDO的各种作用
(对于11gR2版本,不同版本会有些功能差异):
数据回滚(rollback)
    最基本的功能,回滚不需要的操作。
数据库恢复(data recovery)
    在数据库意外宕机之后需要使用UNDO数据进行回滚操作。
一致性读(read consistency)
    提供数据库的一致性读功能,这是一个非常重要的特性。
闪回功能(Flashback)
    除Flashback Database之外其它的闪回都是通过UNDO实现的,包括Flashback Query, Flashback Drop等等。
说到UNDO保存的是数据库中被修改数据的前映像时有人可能会认为Oracle会在数据发生修改的时候将整个数据块复制
到回滚段中,然后在回滚的时候再拷贝回来。而实际上不是这样的,这里所说的前映像只是数据的前映像,
而不是数据块的,这个要明确。一个数据块在发生回滚之后与修改之前并不会是在物理上一样,只能说是逻辑上一样。
要证明这点的最直接的方法也许就是将UNDO块的内容转储(dump)出来看看,但是阅读转储数据是个累人的活儿,
实际上我们还是可以通过其它的方法来进行验证的。在讲完下一小节的“UNDO的操作级别”后会给出验证的方法。


UNDO的产生级别
    理解UNDO产生级别对于理解UNDO什么时候产生,UNDO的产生量以及UNDO空间什么时候可以回收等等这些问题非常的重要。
    其实所谓的UNDO的产生级别就是UNDO是由什么产生的。UNDO的最基本的作用就是回滚了,而回滚所针对的是事务(transaction),
    也就是说UNDO是由事务产生的,或者说UNDO的产生级别是事务。在自动UNDO管理的模式下,当开启一个事务修改数据时,
    Oracle会给这个开启的事务分配回滚段用于存储被修改数据的前映像,在事务回滚或者是提交之前,这些分配的回滚区
    (一个回滚段可以分配给多个事务,因此回滚数据的状态定义在区(extent)而非段(segment)上)的状态称为活动状态(ACTIVE),
    处于活动状态的的回滚区对数据的回滚有着至关重要的作用,因此是不能够被覆盖或者是离线(offline)的。
    如果存在处于活动状态的回滚段丢失(通常是UNDO表空间损坏),这时的未完成事务将因为无法回滚而造成数据的不一致。
    当这个事务提交或者是回滚之后,所对应的回滚区则标记为非活动(Inactive)状态,处于非活动状态的回滚区不再为数据回滚
    或是数据库恢复等功能所用,但是UNDO的其它诸如一致性读和闪回等功能却还是有可能用到这些回滚段。因此处于Inactive的
    回滚区也并不意味着就可以马上丢弃,这个需要取决于UNDO的RETENTION的设置。

注:从术语上说,当使用手工UNDO管理时,所创建的用来存储UNDO数据的数据段称为回滚段(rollback segment),
    而使用自动UNDO管理时由Oracle自己在UNDO表空间中所创建的存储UNDO数据的数据段则称为撤销段(undo segment),
    不过在文中为了方便都统一的称为回滚段。 
    在动态视图V$TRANSACTION中,有几个字段就为我们提供了关于那些正在进行的事务所对应的UNDO段的相关信息:


事务所使用的UNDO段信息
•	XIDUSN NUMBER Undo segment number
•	PRV_XIDUSN NUMBER Previous transaction undo segment number
事务UNDO空间使用情况
•	USED_UBLK NUMBER Number of undo blocks used
•	USED_UREC NUMBER Number of undo records used
事务当前UBA(UNDO块地址)信息
•	UBAFIL NUMBER Undo block address (UBA) filenum
•	UBABLK NUMBER UBA block number
•	UBASQN NUMBER UBA sequence number
•	UBAREC NUMBER UBA record number
事务起始UBA信息
•	START_UBAFIL NUMBER Start UBA file number
•	START_UBABLK NUMBER Start UBA block number
•	START_UBASQN NUMBER Start UBA sequence number
•	START_UBAREC NUMBER Start UBA record number

下面显示的就是一个事务的UNDO信息:

SQL> create table tt0 (a int,b int);

Table created.

SQL> insert into tt0 values (1,2);

1 row created.

SQL> commit;

Commit complete.

SQL> UPDATE tt0 SET a=1 WHERE a=1; 

1 row updated.

SQL> SELECT XID AS "txn id", XIDUSN AS "undo seg", USED_UBLK "used undo blocks", 
     XIDSLOT AS "slot", XIDSQN AS "seq", STATUS AS "txn status"
     FROM V$TRANSACTION; 

txn id             undo seg used undo blocks       slot        seq txn status
---------------- ---------- ---------------- ---------- ---------- ----------------
0A002E0076030000         10                1         46        886 ACTIVE

现在回到上一小节所说的UNDO是否保存的是被修改的数据库的前映像的问题,V$TRANSACTION中的USED_UBLK字段
可以帮我们澄清这个问题:如果UNDO保存的数据块的前映像的话,如果我们修改两个数据快,那USED_UBLK将会是两个,
而非一个。下面就来验证一下。

SQL>insert into tt0 select object_id,data_object_id from dba_objects ;

50009 rows created.



SQL>  SELECT MAX(a),DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) 
      FROM tt0 GROUP BY DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) 
      ORDER BY 1; 

    MAX(A) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
---------- ------------------------------------
       615                                61362
      1252                                61363
      1912                                61364
      2572                                61365
      3232                                61366


   上面可以看到列A值615和1252分别位于块61362和61363上,现在我们修改这两个值,
再看看此时的USED_UBLK会是多少。

SQL> update tt0 set a=615 where a=615;

1 row updated.

SQL> update tt0 set a=1252 where a=1252;

1 row updated.

SQL> SELECT XID AS "txn id", XIDUSN AS "undo seg", USED_UBLK "used undo blocks",
     XIDSLOT AS "slot", XIDSQN AS "seq", STATUS AS "txn status"
     FROM V$TRANSACTION; 

txn id             undo seg used undo blocks       slot        seq txn status
---------------- ---------- ---------------- ---------- ---------- ----------------
0200090087030000          2                1          9        903 ACTIVE

从结果可以看到,USED_UBLK是1,而不是2,这就从侧面说明了UNDO保存的是数据的前映像而非数据块的前映像。
   当然,有个事务信息,我们就可以找到对应的会话相关信息,这也就是我们分析当前正在进行事务UNDO使用情况的一个方法,
   这个后面会说到。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值