ITPub博客

首页 > Linux操作系统 > Linux操作系统 > oracle回滚机制的深入探究 .

oracle回滚机制的深入探究 .

原创 Linux操作系统 作者:houxp666 时间:2012-12-12 17:13:40 0 删除 编辑
undo机制是oracle的巧妙之处,也是学习oracle的难点之一。

    下面我们从内部来具体了解它。

    会话1:scott用户,发起一个事务

  1. hr@ORCL> conn scott/oracle  
  2. Connected.  
  3. scott@ORCL> UPDATE emp SET sal=4000 WHERE empno=7788;  
  4.   
  5. 1 row updated.  
  6.   
  7. scott@ORCL> SELECT empno,ename,job,mgr,sal FROM emp WHERE empno=7788;  
  8.   
  9.      EMPNO ENAME      JOB              MGR        SAL  
  10. ---------- ---------- --------- ---------- ----------   
  11.       7788 SCOTT      ANALYST         7566       4000  


    先不提交这个事务,会话2:SYS用户
    获得事务信息

    从v$transaction,可得:该事务在9号回滚段,位于26号事务槽

  1. sys@ORCL> SELECT xidusn,xidslot FROM v$transaction;  
  2.   
  3.     XIDUSN    XIDSLOT  
  4. ---------- ----------   
  5.          9         26  


    从v$rollstat,也可见该事务高就9号回滚段

  1. sys@ORCL> SELECT usn,xacts FROM v$rollstat;  
  2.   
  3.        USN      XACTS  
  4. ---------- ----------   
  5.          0          0  
  6.          1          0  
  7.          2          0  
  8.          3          0  
  9.          4          0  
  10.          5          0  
  11.          6          0  
  12.          7          0  
  13.          8          0  
  14.          9          1  
  15.         10          0  


    dump回滚段的段头信息

  1. sys@ORCL> SELECT * FROM v$rollname a WHERE a.usn=9;  
  2.   
  3.        USN NAME  
  4. ---------- ------------------------------   
  5.          9 _SYSSMU9$  
  6.   
  7. sys@ORCL> alter system dump undo header '_SYSSMU9$';  
  8.   
  9. System altered.  
  10.   
  11. sys@ORCL> select spid from v$process where addr in (select paddr from v$session where sid in (select sid   
  12.   2  from v$mystat where rownum=1));  
  13.   
  14. SPID  
  15. ------------   
  16. 10086  


    部分内容摘入如下:

  1. ********************************************************************************  
  2. Undo Segment:  _SYSSMU9$ (9)  
  3. ********************************************************************************  
  4.   Extent Control Header  
  5.   -----------------------------------------------------------------   
  6.   Extent Header:: spare1: 0      spare2: 0      #extents: 4      #blocks: 31  
  7.                   last map  0x00000000  #maps: 0      offset: 4080  
  8.       Highwater::  0x00800615  ext#: 2      blk#: 4      ext size: 8  
  9.   #blocks in seg. hdr's freelists: 0  
  10.   #blocks below: 0  
  11.   mapblk  0x00000000  offset: 2  
  12.                    Unlocked  
  13.      Map Header:: next  0x00000000  #extents: 4    obj#: 0      flag: 0x40000000  
  14.   Extent Map  
  15.   -----------------------------------------------------------------   
  16.    0x0080008a  length: 7  
  17.    0x008000d9  length: 8  
  18.    0x00800611  length: 8  
  19.    0x00800669  length: 8  
  20.   
  21.  Retention Table  
  22.   -----------------------------------------------------------   
  23.  Extent Number:0  Commit Time: 1344269736  
  24.  Extent Number:1  Commit Time: 1344276385  
  25.  Extent Number:2  Commit Time: 1344264118  
  26.  Extent Number:3  Commit Time: 1344264252  
  27.   
  28.   TRN CTL:: seq: 0x0105 chd: 0x0019 ctl: 0x0014 inc: 0x00000000 nfb: 0x0000  
  29.             mgc: 0x8201 xts: 0x0068 flg: 0x0001 opt: 2147483646 (0x7ffffffe)  
  30.             uba: 0x00800615.0105.11 scn: 0x0000.000d2615  
  31. Version: 0x01  
  32.   FREE BLOCK POOL::  
  33.     uba: 0x00000000.0105.10 ext: 0x2  spc: 0x16f6  
  34.     uba: 0x00000000.0105.03 ext: 0x2  spc: 0x1eac  
  35.     uba: 0x00000000.0101.0b ext: 0xb  spc: 0x198c  
  36.     uba: 0x00000000.0000.00 ext: 0x0  spc: 0x0  
  37.     uba: 0x00000000.0000.00 ext: 0x0  spc: 0x0  
  38.   TRN TBL::  
  39.   
  40.   index  state cflags  wrap#    uel         scn            dba            parent-xid    nub     stmt_num    cmt  
  41.   ------------------------------------------------------------------------------------------------   
  42.    0x00    9    0x00  0x0162  0x0029  0x0000.000d2ab9  0x00800613  0x0000.000.00000000  0x00000001   0x00000000  1344280244  
  43.              ............................................  
  44.    0x1a   10    0x80  0x0162  0x0002  0x0000.00000000  0x00800615  0x0000.000.00000000  0x00000001   0x00000000  0  
  45.              ............................................  


    这就是神秘的回滚段头的信息,其中包括事务表信息。其中,0x1a是个16进制数,转成10进制:

  1. scott@ORCL> select to_number('1a','xx') from dual;  
  2.   
  3. TO_NUMBER('1A','XX')  
  4. --------------------   
  5.                   26  


   

    由此,可知:0x1a为26.回顾前面的事务信息,该事务正好占用的是第26号事务槽,状态(state)为10代表的是活动事务。

    dump旧值信息
    段头信息的第七列:dba(data block address),指的就是回滚块的地址0x00800615  
   下面把dba翻译一下

  1. sys@ORCL> select to_number('00800615','xxxxxxxx') from dual;  
  2.   
  3. TO_NUMBER('00800615','XXXXXXXX')  
  4. --------------------------------   
  5.                          8390165  
  6.   
  7. sys@ORCL> select dbms_utility.data_block_address_file(8390165) from dual;  
  8.   
  9. DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(8390165)  
  10. ---------------------------------------------   
  11.                                             2  
  12.   
  13. sys@ORCL> select dbms_utility.data_block_address_block(8390165) from dual;  
  14.   
  15. DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(8390165)  
  16. ----------------------------------------------   
  17.                                           1557  


    由此,可知:旧值在2号文件的第1557个回滚块上
    这与从v$transaction查询得到的数据完全一致:

  1. sys@ORCL> select ubafil,ubablk from v$transaction;  
  2.   
  3.     UBAFIL     UBABLK  
  4. ---------- ----------   
  5.          2       1557  


    回到会话1,继续DML事务:scott用户

  1. scott@ORCL> update emp set sal=4000 where empno=7788;  
  2.   
  3. 1 row updated.  
  4.   
  5. scott@ORCL> update emp set sal=4000 where empno=7782;  
  6.   
  7. 1 row updated.  
  8.   
  9. scott@ORCL> update emp set sal=40000 where empno=7698;  
  10.   
  11. 1 row updated.  


    会话2:sys用户
    把回滚块1557dump出来

  1. sys@ORCL> select spid from v$process where addr in (select paddr from v$session where sid in (select sid from v$mystat  where rownum=1));  
  2.   
  3. SPID  
  4. ------------   
  5. 11146  
  6.   
  7. sys@ORCL> alter system dump datafile 2 block 1557;  
  8.   
  9. System altered.  


    回滚块1557里面开头的信息部分如下:

  1. *** 2012-08-07 16:31:42.449  
  2. *** SERVICE NAME:(SYS$USERS) 2012-08-07 16:31:42.355  
  3. *** SESSION ID:(135.102) 2012-08-07 16:31:42.355  
  4. Start dump data blocks tsn: 1 file#: 2 minblk 1557 maxblk 1557  
  5. buffer tsn: 1 rdba: 0x00800615 (2/1557)  
  6. scn: 0x0000.000d36d2 seq: 0x01 flg: 0x04 tail: 0x36d20201  
  7. frmt: 0x02 chkval: 0xbeca type: 0x02=KTU UNDO BLOCK  
  8. Hex dump of block: st=0, typ_found=1  
  9. Dump of memory from 0x0E7E4400 to 0x0E7E6400  
  10. ......................  
  11. ********************************************************************************  
  12. UNDO BLK:  
  13. xid: 0x0009.01a.00000162  seq: 0x105 cnt: 0x14  irb: 0x14  icl: 0x0   flg: 0x0000  
  14.   
  15.  Rec Offset      Rec Offset      Rec Offset      Rec Offset      Rec Offset  
  16. ---------------------------------------------------------------------------   
  17. 0x01 0x1f08     0x02 0x1e58     0x03 0x1df4     0x04 0x1da0     0x05 0x1d1c  
  18. 0x06 0x1ca0     0x07 0x1c54     0x08 0x1b80     0x09 0x1afc     0x0a 0x1a70  
  19. 0x0b 0x198c     0x0c 0x1924     0x0d 0x18cc     0x0e 0x17e8     0x0f 0x1780  
  20. 0x10 0x1728     0x11 0x16a8     0x12 0x1650     0x13 0x15f4     0x14 0x1598  
  21.   
  22. *-----------------------------  


    注意,这部分信息有个参数irb: 0x14。irb指的是回滚段中记录的最近所有未提交的事务的开始之处,也就是最近一次被修改的地方,如果要回滚,这便是回滚的起点。
    由上,可知:(irb: 0x14)的偏移地址为0x1598
    找到irb:0x14信息,如下:

  1. *-----------------------------   
  2. * Rec #0x14  slt: 0x1a  objn: 51148(0x0000c7cc)  objd: 51148  tblspc: 4(0x00000004)  
  3. *       Layer:  11 (Row)   opc: 1   rci 0x13  
  4. Undo type:  Regular undo   Last buffer split:  No  
  5. Temp Object:  No  
  6. Tablespace Undo:  No  
  7. rdba: 0x00000000  
  8. *-----------------------------   
  9. KDO undo record:  
  10. KTB Redo  
  11. op: 0x02  ver: 0x01  
  12. op: C  uba: 0x00800615.0105.13  
  13. KDO Op code: URP row dependencies Disabled  
  14.   xtype: XA flags: 0x00000000  bdba: 0x01000020  hdba: 0x0100001b  
  15. itli: 2  ispac: 0  maxfr: 4858  
  16. tabn: 0 slot: 5(0x5) flag: 0x2c lock: 0 ckix: 191  
  17. ncol: 8 nnew: 1 size: 1  
  18. col  5: [ 3]  c2 1d 33  


    c2 1d 33转换为10进制就是2850.这是最后被更新的记录的旧值。也就是update emp set sal=4000 where empno=7698。

    注意,这里有几个参数需要关注:

    1)参数rci 0x13,该参数代表的就是undo chain(同一个事务中的多次修改,根据chain链接关联),此处的rci 0x13指向第二次修改update emp set sal=4000 where empno=7782.此时,如果有其他进程查询scott.emp表,则oracle需要构造一致性读来把数据展现给用户。
    2)参数bdba: 0x01000020,该参数代表旧值对应的数据块的地址,下面把这个参数翻译出来:

  1. scott@ORCL> select to_number('01000020','xxxxxxxx') from dual;  
  2.   
  3. TO_NUMBER('01000020','XXXXXXXX')  
  4. --------------------------------   
  5.                         16777248  
  6.   
  7. scott@ORCL> select dbms_utility.data_block_address_file(16777248) from dual;  
  8.   
  9. DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(16777248)  
  10. ----------------------------------------------   
  11.                                              4  
  12.   
  13. scott@ORCL> select dbms_utility.data_block_address_block(16777248) from dual;  
  14.   
  15. DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(16777248)  
  16. -----------------------------------------------   
  17.                                              32  


    再将4号文件的第32个块dump出来:

  1. sys@ORCL> select spid from v$process where addr in (select paddr from v$session  
  2.   2  where sid in (select sid from v$mystat where rownum=1));  
  3.   
  4. SPID  
  5. ------------   
  6. 13929  
  7.   
  8. sys@ORCL> alter system dump datafile 4 block 32;  
  9.   
  10. System altered.  


    部分内容摘入如下:

  1. Start dump data blocks tsn: 4 file#: 4 minblk 32 maxblk 32  
  2. buffer tsn: 4 rdba: 0x01000020 (4/32)  
  3. scn: 0x0000.000d36d2 seq: 0x01 flg: 0x04 tail: 0x36d20601  
  4. frmt: 0x02 chkval: 0xa9ea type: 0x06=trans data  
  5. Block header dump:  0x01000020  
  6.  Object id on Block? Y  
  7.  seg/obj: 0xc7cc  csc: 0x00.b9cf3  itc: 2  flg: E  typ: 1 - DATA  
  8.      brn: 0  bdba: 0x1000019 ver: 0x01 opc: 0  
  9.      inc: 0  exflg: 0  
  10.   
  11.  Itl           Xid                  Uba         Flag  Lck        Scn/Fsc  
  12. 0x01   0x0003.011.000000f2  0x00805794.00c8.49  C---    0  scn 0x0000.0006bfdb   
  13. 0x02   0x0009.01a.00000162  0x00800615.0105.14  ----    3  fsc 0x0002.00000000  


    这里存在ITL事务槽信息,事务必须得到一个ITL事务槽才能够进行数据修改。ITL内容主要包括xid(指向回滚段头的ITL)、uba(指向回滚块)、Lck(行头锁的个数,此处修改三次,故有3个锁)。在以上输出中,可知:itl2(0x02)上存在活动事务。

    将xid(0x0009.01a.00000162)分解一下:0009表明该事务指向9号回滚段,01a表明该事务指向26号事务槽,00000162表明该事务第354次被覆盖(因为回滚段是循环使用的)。
    将uba(0x00800615.0105.14)分解一下:00800615表明第1557个回滚块,14是irb信息(回滚的起点)。

    至此,undo段和数据块里面的事务信息被完全解析出来,二者完全一致!

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/263455/viewspace-750983/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2012-11-24

  • 博文量
    46
  • 访问量
    90421