Chinaunix首页 | 论坛 | 博客
  • 博客访问: 703207
  • 博文数量: 26
  • 博客积分: 921
  • 博客等级: 中士
  • 技术积分: 2270
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-06 10:45
个人简介

叶绍琛,Unix/Linux/Android操作系统内核技术专家,大中华区前50位RHCA系统架构师,Oracle OCM认证数据库大师,曾任网易互娱云计算平台技术负责人,关注技术创新,关注云计算背景下的技术变革。

文章分类
文章存档

2014年(3)

2012年(23)

分类: Oracle

2012-11-10 13:29:11

一、什么是回滚段?

     1.  回滚段表空间,Oracle的官方叫法为“还原表空间”:

     还原表空间可以有多个,但在任意一个时刻,只能有一个是当前还原表空间(也可以称为活动还原表空间)。可以使用如下声明随时转换活动还原表空间:alter system set undo_tablespace='还原表空间';

     2.  回滚段:

     在Oracle中,段是逻辑结构中最高一层。表就是段,我们称为表段,索引是索引段,等等。回滚段也是段,我们可以把它看作表,一种由系统自己创建的表。

     系统默认创建11个回滚段,当然,如果还原表空间太小,默认回滚段数量也可能小于这个数字,可如下查看它们的名字:

sys@MYTWO> select * from v$rollname;

       USN NAME

---------- ------------------------------

         0 SYSTEM

        11 _SYSSMU11$

        12 _SYSSMU12$

   :     :

   :     :

        19 _SYSSMU19$

        20 _SYSSMU20$

已选择11行。


将活动还原表空间切换到UNDOTBS3上再看:

sys@MYTWO> select * from v$rollname;

       USN NAME

---------- ------------------------------

         0 SYSTEM

        23 _SYSSMU23$

        24 _SYSSMU24$

        25 _SYSSMU25$


     因为UNDOTBS3只有512K,所以系统默认创建的回滚段只有3个。

     在切换还原表空间后,新还原表空间中的回滚段状态变为ONLINE,原还原表空间回滚段状态变为OFFLINE。可以在 dba_rollback_segs.status列看到这个变化。而v$rollstat.status列则显示非OFFLINE的回滚段的状态。如果发现某回滚段的V$rollstat.status列值为PENDING OFFLINE,说明此回滚段在切换前的还原表空间中,尚有末决事务。待到末决事务提交后,状态自然会变为OFFLINE

还原表空间中回滚段的数量是会根据情况调整的。当繁忙时,系统将会自动创建更多的回滚段,空闲时系统也会自动回收回滚段。我们也可以从告警日志中看到回滚段的创建与回收。


3、观察UNDOTBS3回滚段:

     UNDOTBS3是我们后面的练习需要频繁使用的还原表空间,它共有512K字节,128个块。下面我们通过DBA_UNDO_EXTENTS观察一下UNDOTBS3中回滚段的区占用情况:

     sys@MYTWO> select * from dba_undo_extents where segment_name='_SYSSMU25$';(省去部分列)

OWN SEGMENT_NAME  TABLESPACE_NAME EXTENT_ID FILE_ID BLOCK_ID BYTES BLOCKS 

--- ------------------------------ ------------------------------ ---------- ---------- ---------- ---------- ---------- -----------

SYS _SYSSMU25$           UNDOTBS3           0            14         82        61440       15

SYS _SYSSMU25$           UNDOTBS3           1            14         97        65536       16


     从以上结果可以看到_SYSSMU25$回滚段占用两个区,0号区从第82号块开始到96号块,共15个块。1号区从97号块开始到112号块,共16个块。为什么1号区比0号区多一个块?这是因为第81块被作为了回滚段头,回滚段头要保存重要信息:事务表,下面马上就要讲到了。从第82号块开始才可以保存回滚记录。我们也可以从DBA_EXTENTS中得到同样的结果。

     用上面的命令观察一下UNDOTBS3中的每一个回滚段,画一个简要的关于每个回滚段空间占用情况的图,要对这些回滚段的区、块的分部有印象,这样才能更好的明白下面章节的内容。

UNDOTBS3中的回滚段,每个各占两个区,这是因为通常的回滚段,最小就是两个区。


二、相关参数介绍:
     1.UNDO_MANAGEMENT:这个参数确定了Undo空间的管理方式。该参数是个静态参数(不可以动态修改)。如果设置为MANUAL,则使用rollback-managed undo (RMU)管理模式;如果设置为AUTO,则使用system-managed undo (SMU) 或者automatically managed undo (AMU)管理模式。在Oracle 9i数据库中,AUTO是缺省值。

     2.UNDO_TABLESPACE:只有使用system-managed undo (SMU) 或者automatically managed undo (AMU)管理模式的时候才需要设置这个参数。它指定了SMU或者AMU所使用的Undo表空间(该表空间必须是已经创建的表空间)。这个设置可以通过ALTER SYSTEM命令动态改变。如果忽略设置这个参数,那么数据库中的第一个Undo表空间就会被使用,如果没有可用的Undo表空间,SYSTEM 回滚段就会被使用。创建Undo Tablespace的命令如下:

     SQL> CREATE UNDO TABLESPACE UNDO_TEST  DATAFILE 'E:\TEST_TEST.ora' SIZE 10M 

AUTOEXTEND ON NEXT 2M MAXSIZE 700M;

     表空间已创建。将刚才创建的回滚表空间设为当前回滚表空间:

         scott@MYTWO> alter system set undo_tablespace='UNDO_TEST';

     在创建回滚段表空间时,注意区管理只能是自动,段管理方式只能是手动。


     3.UNDO_RETENTION:只有使用system-managed undo (SMU) 或者automatically managed undo (AMU)管理模式的时候才需要设置这个参数。它指定了在重做表空间中保持重做的时间,这个设置可以通过ALTER SYSTEM命令动态改变,缺省是3小时。保留重做主要有两个目的,一个是为冗长查询保留非活动的(inactive)的正在被使用的数据,另一个是支持显示当前数据前一种状态的查询,即Oracle 9i中“Flashback Query”新特性。例如,如果设置UNDO_RETENTION = 10800,那么Oracle将尽最大可能将重做保留3小时,即3小时的查询不会报ORA-01555错误。


     4.UNDO_SUPPRESS_ERROR:当使用SMU管理模式时,你不能运行RMU管理模式的管理命令,比如说把一个回滚段联机或者脱机等等。这个参数决定了当使用SMU管理模式时,如果发出RMU管理模式的管理命令是否产生错误信息。这个设置可以通过ALTER SYSTEM命令动态改变,缺省值是FALSE,即不禁止错误信息。


三、回滚段的使用:

1. 事务表:

回滚段中第一个块是回滚段头,它控制着回滚段的改变数据的写。在此回滚段头中,有一个事务表,每一个活动的事务,在各回滚段事务表中都要占一行。

当还原表空间空间足够时,Oracle倾向于让每个事务各占一个回滚段。否则,会让多个事务占用一个回滚段。每回滚段的第一个块,又被称为回滚段头,通常被事务表占用。事务表中保存本回滚段中的所有事务信息。默认的事务表的数量根据块大小而不同,此数值不可增加,它根据块大小的不同而不同。事务表中的每一行,又称为一个事务槽(slot)。


2.  如果回滚段中有多个事务,回滚段中的区会被多个事务占用,但任一回滚块中只能有一个事务。

     下面我们用例子来看看回滚段的使用情况:


1

scott@MYTWO> update t8 set c='AA' where id=1;

已更新 行。

观察事务情况:(只显示相关列)

sys@MYTWO> select xidusn,xidslot,xidsqn,ubafil,ubablk,ubasqn,ubarec,status,

start_time,start_scnb,start_scnw,start_uext,start_ubafil,start_ubablk,start_ubasqn,

used_ublk,used_urec,log_io,phy_io,cr_get,cr_change from v$transaction;

sys@MYTWO> select xidusn,xidslot,xidsqn,ubafil,ubablk,ubasqn,ubarec,status,start_time,start_sc

    XIDUSN    XIDSLOT     XIDSQN     UBAFIL     UBABLK     UBASQN     UBAREC STATUS

---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------------

        23          1         52         14         20         21          7 ACTIVE

可以看到,事务1占用23号回滚段中的20块。


2

继续打开不同的会话,更新T8表:

update t8 set c='AA' where id=2;

update t8 set c='AA' where id=3;

update t8 set c='AA' where id=4;

     UNDOTBS3中的空间比较小,默认的回滚段只有3个,并且随事务增多,并不会再新增回滚段,我们现在已经有四个事务了,此时应该会有两个事务共用一个回滚段了,显示如下:

    XIDUSN    XIDSLOT     XIDSQN     UBAFIL     UBABLK     UBASQN     UBAREC STATUS

---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------------

        24         14         12         14         55          4          2 ACTIVE

        25         11         13         14         88          4          3 ACTIVE

        25         14         13         14         89          4          3 ACTIVE

        23          1         52         14         20         21          7 ACTIVE

     回滚段_SYSSMU25$中有两个事务,一个事务占用88块,一个占用89块,它们都在0号区中。上面我们提到过了,一个回滚块中只能有一个事务,但区中可以有多个事务。

     25号回滚段中的两个事务的槽号分别是1114,即,它们占用事务表的第1114行,下面我们DUMP回滚段头看看:

Alter system dump undo header _SYSSMU25$;

  index  state    cflags  wrap#    uel         scn            dba   

  ----------------------------------------------------------------------------------------------

   0x00    9    0x00  0x000d  0x0001  0x0000.0084616a  0x03800054 

   0x0b   10    0x80  0x000d  0x0000  0x0000.008463ce  0x03800058 

   0x0e   10    0x80  0x000d  0x0000  0x0000.008463ee  0x03800059 

   0x15    9    0x00  0x000c  0x0000  0x0000.00845ff9  0x03800054 

     State列为10,代表此行是一个活动事务,相应的,活动事务的cflags列一般为0x80Wrap#列就是V$transcation中的XIDSQN列,这一列也被称为“序列号”,它表示此回滚槽被重用的次数。例子中值是0x000d,即,是第13次被重用。回滚段编号、回滚段槽号和序列号它们三个和起来唯一的代表一个活动的事务。通常它们被称为事务序列号――XID。从V$transcation中的列名,已经可以看起来这一点。

事务表中的UEL列表示事务的当前区,上例中两个事务都在0号区。

     SCN列是事务开始的SCN,在V$transcationSTART_SCNB列也有事务开始的SCN号。

     DBA是事务所占数据文件编号、块编号。


3

     XID25.11.13的事务中,继续修改,注意,一个块中可以容纳T8表的三行,回滚也不例外,

update t8 set c='AA' where id=5;

update t8 set c='AA' where id=6;

     到现在为止,25.11.13事务已经修必了三条记录,分别是ID356的。无论这三条记录原来分别在哪些块中,它们的前映像信息,在14号文件的80号块中。再分布一条更新命令:

     update t8 set c='AA' where id=7;

查看事务信息:

XIDUSN  XIDSLOT  XIDSQN     UBAFIL     UBABLK START_UBAFIL USED_UBLK USED_UREC

---------- ---------- ---------- ---------- ---------- ---------- ---------- -------------------------- ---------- ---------- -------

  24         14         12         14         55          55 1 1

  25         11         13         14         90          88 2 4

  25         14         13         14         89          89 1 1

  23          1         52         14         20          20 1 1

     可以看到25.11.13事务当前占用的块是90。在START_UBAFIL列中,是它的开始所占用的块编号,88USED_UBLK表示它共占2块,USED_UREC表示它共有4条回滚记录,这代表此事务进行过4次修改。如果你对同一行修改两次,它也会生成两条回滚记录。再发布修改声明如下:

 update t8 set c=lower(c) where id=6;

 update t8 set c=lower(c) where id=7;

ID67的行上面我们已经修改过一次,现在是第二次修改,查看事务信息:

XIDUSN  XIDSLOT  XIDSQN     UBAFIL     UBABLK START_UBAFIL USED_UBLK USED_UREC

---------- ---------- ---------- ---------- ---------- ---------- ---------- -------------------------- ---------- ---------- -------

  24         14         12         14         55          55 1 1

  25         11         13         14         90          88 2 6

  25         14         13         14         89          89 1 1

  23          1         52         14         20          20 1 1

     从加方框处可以看到,25.11.13事务已经生成了6条回滚记录。

     由于T8表中行非常的大,所以每个回滚块中只能容纳3条回滚记录,现在,25.11.13正好占满2个回滚块。

     25.11.13中再发布一条声明:

     update t8 set c='e' where id=5;

查看事务信息:

XIDUSN  XIDSLOT  XIDSQN     UBAFIL     UBABLK START_UBAFIL USED_UBLK USED_UREC

---------- ---------- ---------- ---------- ---------- ---------- ---------- -------------------------- ---------- ---------- -------

  24         14         12         14         55          55 1 1

  25         11         13         14         91          88 3 7

  25         14         13         14         89          89 1 1

  23          1         52         14         20          20 1 1

     25.11.13当前占用已经有3个回滚块了,从88块开始,分别是889091

     现在,是否了解了事务是如何占用回滚块的?当有新事务产生时,Oracle都要查询段头的事务表,然后找一个空闲的、且序列号值最低的槽分配给事务,然后,跟据已占用的槽的DBA,决定新事务应该在哪一块中,通常都是紧接着上一事务分配新的回滚块。


3、回滚块与回段链

     上例中的25.11.13事务共有7条回滚记录,占用3个回滚块,从最后一条记录开始,这7条记录每条有一个指向前面记录的信息,这7条记录顺序连成一串,所以又叫回滚链。下面让我们从最后一条记录开始,顺链追踪,看看回滚记录在回滚块中是如何分配的。


2_2

1DUMP回滚链中最后一个块:

Alter system dump datafile 14 block 91;

打开文件查看如下:

********************************************************************************

UNDO BLK:  

xid: 0x0019.00b.0000000d  seq: 0x4   cnt: 0x1   irb: 0x1   icl: 0x0   flg: 0x0000

这里有一个irb:0x1,它指示回滚链尾端在此块中的记录号,此处0x1是指块中是第一条回滚记录。

这里的Seq0x4也很重要,它带表回滚段块被循环使用的次数,后面我们要讲到这个值的详细作用。

 Rec Offset      Rec Offset      Rec Offset      Rec Offset      Rec Offset

---------------------------------------------------------------------------

0x01 0x0bac     

这是所有回滚记录相对于块首的偏移量,第一条记录偏移量是0x0bac

*-----------------------------

* Rec #0x1(回滚记录号)slt: 0x0b(槽号)objn: 6957(0x00001b2d)dba_objects.object_id列,此处是T8的对象号)

  objd: 7627dba_objects.data_object_id列,T8的对象号)  tblspc: 5(0x00000005)T8所在表空间编号)

*       Layer:  11 (Row)   opc: 1   rci 0x00(此块中,回滚链中前一回滚记录的编号)   

Undo type:  Regular undo   Last buffer split:  No 

Temp Object:  No 

Tablespace Undo:  No 

rdba: 0x0380005a

(回滚链中前一块所在位置,此处是14号文件90块,如果RCI和此值都为0,则证明已经到了回滚链的头部)

     rci 0x00看到,在此块中,已没有回滚链相关记录,从rdba: 0x0380005a中看到回滚链并没有结束,它的前一条记录在14号文件90号块中。

     再下面的信息就是回滚记录的内容了,此处是T8C列的前映像。回想刚才所做过的更新,此处不再列出。


2DUMP回滚链中前一个块:第90

alter system dump datafile 14 block 90;

此内容如下:

********************************************************************************

UNDO BLK:  

xid: 0x0019.00b.0000000d  seq: 0x4   cnt: 0x3   irb: 0x3   icl: 0x0   flg: 0x0000

irb: 0x3指示回滚链在此块中最后一个回滚记录是第3条。

找到第三条记录,

*-----------------------------

* Rec #0x3  slt: 0x0b  objn: 6957(0x00001b2d)  objd: 7627  tblspc: 5(0x00000005)

*       Layer:  11 (Row)   opc: 1   rci 0x02   

Undo type:  Regular undo   Last buffer split:  No 

Temp Object:  No 

Tablespace Undo:  No 

rdba: 0x00000000

*-----------------------------

rci 0x02指示回滚链前一记录在块中第2条回滚记录中。rdba: 0x000000000,指示回滚链前一记录就在本块中。根据第2条记录向前找,找到第1条记录:

*-----------------------------

* Rec #0x1  slt: 0x0b  objn: 6957(0x00001b2d)  objd: 7627  tblspc: 5(0x00000005)

*       Layer:  11 (Row)   opc: 1   rci 0x00   

Undo type:  Regular undo   Last buffer split:  No 

Temp Object:  No 

Tablespace Undo:  No 

rdba: 0x03800058

*-----------------------------

rdba: 0x03800058 指示回滚还没完,它的前一记录在14号文件中88号块中。


3:继续DUMP回滚链中前一个块:第88

********************************************************************************

UNDO BLK:  

xid: 0x0019.00b.0000000d  seq: 0x4   cnt: 0x5   irb: 0x5   icl: 0x0   flg: 0x0000

根据irb: 0x5的指示,从第5条记录向前找,找到第3条回滚记录时,它的信息如下:

*-----------------------------

* Rec #0x3  slt: 0x0b  objn: 6957(0x00001b2d)  objd: 7627  tblspc: 5(0x00000005)

*       Layer:  11 (Row)   opc: 1   rci 0x00   

Undo type:  Regular undo    Begin trans    Last buffer split:  No 

Temp Object:  No 

Tablespace Undo:  No 

rdba: 0x00000000

Rci0rdba0,并且有Begin trans标志,表示这已经是回滚链头了。


当用户回滚事务时,首先从事务表中取出回滚链尾端的DBA,本例是0x0380005b,即91块,在此块中找到回滚链最尾端记录,如下:

*-----------------------------

KDO undo record:

KTB Redo 

op: 0x02  ver: 0x01  

op: C  uba: 0x0380005a.0004.02

KDO Op code: URP row dependencies Disabled

  xtype: XA  bdba: 0x0141fff0  hdba: 0x0141ffe3

itli: 1  ispac: 0  maxfr: 2401

tabn: 0 slot: 1(0x1) flag: 0x2c lock: 1 ckix: 0

ncol: 2 nnew: 1 size: 0

col  0: [1000]

 41 41 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20

(…………省去无用行…………)

     bdba: 0x0141fff0 指示此回滚记录对应的原记录所在的文件号和块号,此处是5号文件131056块。tabn: 0表示表编号。slot: 1(0x1)代表行号,从0开始记数,即第2行。即此回滚记录记载着5号文件131056块第2行的前映像。回滚时,即将前映像 41 41 (字符串“EE”)重新写入5.131056.2处。

阅读(13154) | 评论(2) | 转发(4) |
给主人留下些什么吧!~~

ctohome2014-08-21 02:18:13

叶绍琛2012-11-10 14:54:09

自己沙发!欢迎好友们斧正!