2011年8月6日土曜日

[事务相关] 事务执行过程解析

事务内部示意图

-- 事务执行顺序

-- 一个事务开始时,需要在回滚段事务表上分配一个事务槽
-- 获得表的TM锁,用于保护事务执行过程中,其他用户不能修改表结构
-- 在所要修改的数据块头上,获取一个ITL表中申请一个空闲表项,来记录事务要使用的回滚段地址(上述事务槽)
-- 在修改之前,要记录前镜像信息,这个信息以undo record的形式存储在回滚段的block中,回滚段头事务槽信息指向该record地址,用于回滚恢复或一致性读
-- 锁定修改行,修改行锁定位(LB)(ITL索引)指向申请的ITL表项
-- 数据可以修改
-- 当其他用户并发修改这表记录时,会根据记录头的ITL索引找到ITL表项内容,看这个事务是否已提交,若未提交,这个用户的TX锁会等待前一个用户的TX锁的释放

----------------------------------------------------------------------
-- 测试表
go@DEMO> select empno, sal from emp;
     EMPNO  SAL
---------- ----
      7782 2450
      7788 3000

2 rows selected.

-- 更新1条记录,不提交
go@DEMO> update emp set sal = 4000 where empno = 7788;

1 row updated.

-- 再更新1条信息,并不提交
go@DEMO> update emp set sal = 4000 where empno = 7782;

1 row updated.

-- 查询事务信息(10进制)
-- XIDUSN -- 回滚段号
-- XIDSLOT -- 回滚段槽位
-- UBABLK -- 保存本次事务前镜像的回滚段数据块号
-- UBAFIL --- 回滚段数据块所在数据文件号
go@DEMO> select xidusn, xidslot, xidsqn, ubablk, ubafil, ubarec from v$transaction;
    XIDUSN    XIDSLOT     XIDSQN     UBABLK     UBAFIL     UBAREC
---------- ---------- ---------- ---------- ---------- ----------
         3         43       4583       1569          2         56

1 row selected.

-- 查询回滚段名
go@DEMO> select * from v$rollname where usn = 3;
       USN NAME
---------- ----------------------------------------
         1 _SYSSMU3$

1 row selected.

-- dump回滚段头信息
go@DEMO> alter system dump undo header '_SYSSMU3$';

System altered.

-- 回滚段头信息
-- index = xidusn
-- state = 10 -- 活动事务
-- dba (a × 16 + 4 = 164 = ubablk) -- 回滚段块地址(10位文件地址+22位块地址)
Undo Segment:  _SYSSMU1$ (1)
TRN TBL::
  index  state cflags  wrap#    uel         scn            dba  
  ----------------------------------------------------------------
   0x2b   10    0x80  0x11e7  0x0002  0x0000.002d9234  0x00800621

-- dump保存本次事务前镜像的undo数据块内容
go@DEMO> alter system dump datafile 2 block 1569;

System altered.

-- undo block内容
-- xid -- 事务ID -- 回滚段号 + 事务表槽位 + wrap
-- irb -- 回滚段中记录的最新的未提交变更开始处,如果开始回滚,这是起始搜索点,通过irb可以找到前镜像数据
-- rci -- 本次事务中undo chain的下个偏移量,如果开始回滚,这是下一个需要回滚的修改,通过rci可以找到镜像数据,指针为0x00时,说明本记录已经是本次事务中能够回滚的最后一个
-- 事务回滚顺序与事务执行顺序相反
UNDO BLK: 
xid: 0x0003.02b.000011e7  seq: 0x200 cnt: 0x38  irb: 0x38  icl: 0x0   flg: 0x0000

 Rec Offset      Rec Offset      Rec Offset      Rec Offset      Rec Offset
---------------------------------------------------------------------------
0x01 0x1f74     0x02 0x1f24     0x03 0x1e88     0x04 0x1e20     0x05 0x1d4c    
0x06 0x1ca4     0x07 0x1bfc     0x08 0x1b54     0x09 0x1aec     0x0a 0x1a84    
0x0b 0x1a1c     0x0c 0x19b4     0x0d 0x194c     0x0e 0x18e4     0x0f 0x183c    
0x10 0x17d4     0x11 0x172c     0x12 0x16c4     0x13 0x165c     0x14 0x15f4    
0x15 0x154c     0x16 0x14e4     0x17 0x143c     0x18 0x13d4     0x19 0x132c    
0x1a 0x12c4     0x1b 0x125c     0x1c 0x11f4     0x1d 0x114c     0x1e 0x10e4    
0x1f 0x107c     0x20 0x0fd4     0x21 0x0f2c     0x22 0x0e84     0x23 0x0de0    
0x24 0x0d38     0x25 0x0c94     0x26 0x0bec     0x27 0x0b48     0x28 0x0aa0    
0x29 0x09f8     0x2a 0x0990     0x2b 0x0928     0x2c 0x08c0     0x2d 0x0858    
0x2e 0x07f0     0x2f 0x0768     0x30 0x0730     0x31 0x06d4     0x32 0x0678    
0x33 0x0628     0x34 0x0584     0x35 0x04e0     0x36 0x040c     0x37 0x035c    
0x38 0x0304    

-- 上述irb所指向的修改 -- 本次事务最后一次的未提交的修改
-- rci -- undo chain -- 指向本次事务前一个修改
-- bdba -- 前镜像对应的锁修改的数据块地址(0x014001a4 = file 5 420 block)
*-----------------------------
* Rec #0x38  slt: 0x2b  objn: 46409(0x0000b549)  objd: 46409  tblspc: 5(0x00000005)
*       Layer:  11 (Row)   opc: 1   rci 0x37  
Undo type:  Regular undo   Last buffer split:  No
Temp Object:  No
Tablespace Undo:  No
rdba: 0x00000000
*-----------------------------
KDO undo record:
KTB Redo
op: 0x02  ver: 0x01 
op: C  uba: 0x00800621.0200.37
KDO Op code: URP row dependencies Disabled
  xtype: XA flags: 0x00000000  bdba: 0x014001a4  hdba: 0x014001a3
itli: 2  ispac: 0  maxfr: 4858
tabn: 0 slot: 6(0x6) flag: 0x2c lock: 0 ckix: 50
ncol: 8 nnew: 1 size: 1

-- 本次变更的前镜像
col  5: [ 3]  c2 19 33

-- 上述rci指向的本次事务前一个修改
-- rci 0x00 -- 本次事务到此结束
*-----------------------------
* Rec #0x37  slt: 0x2b  objn: 46409(0x0000b549)  objd: 46409  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
*-----------------------------
uba: 0x00800621.0200.36 ctl max scn: 0x0000.002cea32 prv tx scn: 0x0000.002cea38
txn start scn: scn: 0x0000.002d9216 logon user: 46
 prev brb: 8390172 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x04  ver: 0x01 
op: L  itl: xid:  0x000a.005.000011e1 uba: 0x008005ea.01e6.04
                      flg: C---    lkc:  0     scn: 0x0000.002cd053
Array Update of 1 rows:
tabn: 0 slot: 7(0x7) flag: 0x2c lock: 0 ckix: 3
ncol: 8 nnew: 1 size: 0
KDO Op code:  21 row dependencies Disabled
  xtype: XAxtype KDO_KDOM2 flags: 0x00000080  bdba: 0x014001a4  hdba: 0x014001a3
itli: 2  ispac: 0  maxfr: 4858
vect = 30

-- 前镜像
col  5: [ 2]  c2 1f

-- 在内存中查找变更过的数据块
-- class = 4 -- 段头
-- class = 1 -- 数据块
sys@DEMO> select
    b.segment_name,
    a.file#,
    a.dbarfil,
    a.dbablk,
    a.class,
    a.state,
    decode(bitand(flag,1), 0, 'N', 'Y') DIRTY
from
    x$bh a,
    dba_extents b
where
    b.RELATIVE_FNO = a.dbarfil
and b.BLOCK_ID <= a.dbablk
and b.block_id + b.blocks > a.dbablk
and b.owner='GO' and b.segment_name='EMP';
SEGMENT_NAME         FILE#    DBARFIL     DBABLK      CLASS      STATE DI
--------------- ---------- ---------- ---------- ---------- ---------- --
EMP                      5          5        420          1          1 N
EMP                      5          5        419          4          1 N

2 rows selected.

-- 其他会话再查询emp表,会出现一致读产生的数据块
sys@DEMO> select empno, sal from go.emp;
     EMPNO  SAL
---------- ----
      7782 2450
      7788 3000

2 rows selected.

-- 420 块出现2个,其中STATE = 3 的是一致读产生的数据块
sys@DEMO> select
    b.segment_name,
    a.file#,
    a.dbarfil,
    a.dbablk,
    a.class,
    a.state,
    decode(bitand(flag,1), 0, 'N', 'Y') DIRTY
from
    x$bh a,
    dba_extents b
where
    b.RELATIVE_FNO = a.dbarfil
and b.BLOCK_ID <= a.dbablk
and b.block_id + b.blocks > a.dbablk
and b.owner='GO' and b.segment_name='EMP';
SEGMENT_NAME         FILE#    DBARFIL     DBABLK      CLASS      STATE DI
--------------- ---------- ---------- ---------- ---------- ---------- --
EMP                      5          5        420          1          1 N
EMP                      5          5        420          1          3 Y
EMP                      5          5        419          4          1 N

3 rows selected.

-- dump block 内容
go@DEMO> alter system dump datafile 5 block 420;

System altered.

-- ITL事务槽
-- 表数据块上同样存在指向回滚段的事务信息
-- xid -- 事务ID
-- uba undo block address -- 前镜像地址 + seq + irb
-- lck -- lock status
-- Flag -- 事务状态

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0005.02a.000011e7  0x008000c3.0237.28  C---    0  scn 0x0000.002ceaaa
0x02   0x000a.005.000011e1  0x008005ea.01e6.04  C---    0  scn 0x0000.002cd053

-- 本次事务所分配的事务槽
-- xid -- 指向回滚段事务表的xid
-- uba -- 指向undo block address -- 保存前镜像的undo块地址
0x03   0x0001.026.000011ed  0x00800541.022c.05  C---    0  scn 0x0000.002cd700

-- LB -- 可以找到被修改掉的记录,锁定位信息0x02,指向ITL事务槽
tab 0, row 0, @0x1f8d
tl: 19 fb: --H-FL-- lb: 0x03  cc: 5
col  0: [ 3]  c2 16 5b
col  1: [ 1]  80
col  2: [ 2]  c1 07
col  3: [ 2]  c1 0a
col  4: [ 3]  c2 07 62

0 件のコメント:

コメントを投稿