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使用情况的一个方法,
这个后面会说到。
UNDO管理之一:UNDO基础
最新推荐文章于 2022-05-24 22:08:30 发布