/*
回滚段中第一个块是回滚段头
段头有事务表
事务表中每一行叫 事务槽, 若被分配则唯一对应一个xid
事务槽中的dba指向undo块,块内的rec记录了该事务所做的最后一次修改的块的前镜像(改了几列就只存几列)
对于某一个列的多次修改,或一个事务中修改多个列, 通过UNDO Chain 回滚链来回溯
回滚和一致读时需要依靠UNDO Chain
undo块块头有irb 0x??,指向块内的一条rec,这个rec描述占用该块当前事务的最后一次操作的前镜像(一个块中只能有一个事务)
rec又有两个属性:rci 和 rdba,rci是UNDO Chain,在同一个block内的下一个偏移量,如果为0,就要判断rdba
rdba不为0说明UNDO Chain的下一个变化是记录在另外的一个undo块内,一直回溯,直到rci 和 rdba都为0
表示已经到了事务的起始处,如果是rollback,undo应用到这里就可以结束了.
事务的末尾 irb --> undorec.rci --> until rci=0,rdba!=0 --
--> rdba.rci --> undorec.rci --> until rci=0,rdba=0 事务的开始
*/
/* session 1 */
session_1> select * from emp where empno = 7788;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- ------------------ ---------- ---------- ----------
7788 SCOTT ANALYST 7566 19-APR-87 3000 20
session_1> update emp set sal = 4000 where empno = 7788;
1 row updated.
/* session 2 */
session_2> select xidusn, xidslot, xidsqn, ubafil, ubablk, ubarec from v$transaction;
XIDUSN XIDSLOT XIDSQN UBAFIL UBABLK UBAREC
---------- ---------- ---------- ---------- ---------- ----------
9 6 1823 3 514 44
/* undo段为9号段,事务槽为6号事务槽,事务槽seq为1823,undo块为3号文件第514块第44号记录 */
session_2> select usn, writes, rssize, xacts, hwmsize, wraps from v$rollstat;
USN WRITES RSSIZE XACTS HWMSIZE WRAPS
---------- ---------- ---------- ---------- ---------- ----------
0 5400 385024 0 385024 0
1 1889426 9560064 0 9560064 2
2 2283350 12705792 0 12705792 3
3 2109070 10674176 0 10674176 2
4 1661840 7528448 0 7528448 2
5 1494388 5496832 0 5496832 1
6 2897708 8577024 0 8577024 3
7 4958926 8642560 0 8642560 8
8 3456156 18014208 0 18014208 4
9 2428012 8577024 1 8577024 3
10 2650018 8577024 0 8577024 3
11 rows selected.
session_2> select * from v$rollname where usn = 9;
USN NAME
---------- ------------------------------
9 _SYSSMU9_776660700$
session_2> alter system dump undo header '_SYSSMU9_776660700$';
System altered.
session_2> select value from v$diag_info where name like '%File'
2 ;
VALUE
-----------------------------------------------------------------------------
/opt/oracle/diag/rdbms/myorcl11/myorcl11/trace/myorcl11_ora_5267.trc
session_2> !sz /opt/oracle/diag/rdbms/myorcl11/myorcl11/trace/myorcl11_ora_5267.trc
rz
Starting zmodem transfer. Press Ctrl+C to cancel.
100% 9 KB 9 KB/s 00:00:01 0 Errors
sz 3.48 01-27-98 finished.
/* 部分信息 */
********************************************************************************
Undo Segment: _SYSSMU9_776660700$ (9)
********************************************************************************
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 11 #blocks: 1047
last map 0x00000000 #maps: 0 offset: 4080
Highwater:: 0x00c00202 ext#: 6 blk#: 2 ext size: 128
#blocks in seg. hdr's freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 6
Unlocked
Map Header:: next 0x00000000 #extents: 11 obj#: 0 flag: 0x40000000
*** 2013-11-25 23:32:28.375
Extent Map
-----------------------------------------------------------------
0x00c00101 length: 7
0x00c00130 length: 8
0x00c02200 length: 128
0x00c02380 length: 128
0x00c02b80 length: 128
0x00c02f80 length: 128
0x00c00200 length: 128
0x00c00108 length: 8
0x00c00f00 length: 128
0x00c01e00 length: 128
0x00c01000 length: 128
Retention Table
-----------------------------------------------------------
Extent Number:0 Commit Time: 1385280008
Extent Number:1 Commit Time: 1385280008
Extent Number:2 Commit Time: 1385280490
Extent Number:3 Commit Time: 1385380837
Extent Number:4 Commit Time: 1385388110
Extent Number:5 Commit Time: 1385392012
Extent Number:6 Commit Time: 1385254168
Extent Number:7 Commit Time: 1385254840
Extent Number:8 Commit Time: 1385265240
Extent Number:9 Commit Time: 1385268007
Extent Number:10 Commit Time: 1385279998
TRN CTL:: seq: 0x0287 chd: 0x0012 ctl: 0x0004 inc: 0x00000000 nfb: 0x0000
mgc: 0xb000 xts: 0x0068 flg: 0x0001 opt: 2147483646 (0x7ffffffe)
uba: 0x00c00202.0287.2c scn: 0x0000.007e504b
Version: 0x01
FREE BLOCK POOL::
uba: 0x00000000.0287.2b ext: 0x6 spc: 0x874
uba: 0x00000000.0286.03 ext: 0x5 spc: 0x1c28
uba: 0x00000000.0286.13 ext: 0x5 spc: 0x1968
uba: 0x00000000.0000.00 ext: 0x0 spc: 0x0
uba: 0x00000000.0000.00 ext: 0x0 spc: 0x0
TRN TBL:: /* 回滚段头事务表 */
index state cflags wrap# uel scn dba parent-xid nub stmt_num cmt
------------------------------------------------------------------------------------------------
0x00 9 0x00 0x071f 0x0011 0x0000.007e537c 0x00c00201 0x0000.000.00000000 0x00000001 0x00000000 1385392613
0x01 9 0x00 0x071e 0x000c 0x0000.007e52fa 0x00c00200 0x0000.000.00000000 0x00000001 0x00000000 1385392409
0x02 9 0x00 0x071d 0x0007 0x0000.007e51cd 0x00c00200 0x0000.000.00000000 0x00000001 0x00000000 1385392012
0x03 9 0x00 0x071e 0x0019 0x0000.007e54e4 0x00c00202 0x0000.000.00000000 0x00000001 0x00000000 1385393213
0x04 9 0x00 0x071e 0xffff 0x0000.007e5541 0x00c00202 0x0000.000.00000000 0x00000001 0x00000000 1385393311
0x05 9 0x00 0x071e 0x0013 0x0000.007e5120 0x00c02fff 0x0000.000.00000000 0x00000001 0x00000000 1385391868
0x06 10 0x80 0x071f 0x0006 0x0000.007e557b 0x00c00202 0x0000.000.00000000 0x00000001 0x00000000 0
/* index=6 为数据槽号,state 为10代表的是活动事务 dba 0x00c00202 指向的是包含这个事务的前镜像的数据块地址 */
0x07 9 0x00 0x071e 0x0018 0x0000.007e51de 0x00c00200 0x0000.000.00000000 0x00000001 0x00000000 1385392012
0x08 9 0x00 0x071d 0x001e 0x0000.007e5089 0x00c02fff 0x0000.000.00000000 0x00000001 0x00000000 1385391650
.................
0x21 9 0x00 0x071e 0x0003 0x0000.007e54d4 0x00c00202 0x0000.000.00000000 0x00000001 0x00000000 1385393213
EXT TRN CTL::
usn: 9
sp1:0x00000000 sp2:0x00000000 sp3:0x00000000 sp4:0x00000000
sp5:0x00000000 sp6:0x00000000 sp7:0x00000000 sp8:0x00000000
EXT TRN TBL::
index extflag extHash extSpare1 extSpare2
---------------------------------------------------
0x00 0x00000000 0x00000000 0x00000000 0x00000000
0x01 0x00000000 0x00000000 0x00000000 0x00000000
..........
/* dba 0x00c00202 指向的是包含这个事务的前镜像的undo数据块地址 */
SELECT DBMS_UTILITY.data_block_address_file (
TO_NUMBER (LTRIM ('0x00c00202', '0x'), 'xxxxxxxx'))
AS file_no,
DBMS_UTILITY.data_block_address_block (
TO_NUMBER (LTRIM ('0x00c00202', '0x'), 'xxxxxxxx'))
AS block_no
FROM DUAL;
FILE_NO BLOCK_NO
---------- ----------
3 514
验证了
session_2> select xidusn, xidslot, xidsqn, ubafil, ubablk, ubarec from v$transaction;
XIDUSN XIDSLOT XIDSQN UBAFIL UBABLK UBAREC
---------- ---------- ---------- ---------- ---------- ----------
9 6 1823 3 514 44
/* undo段为9号段,事务槽为6号事务槽,事务槽seq为1823,undo块为3号文件第514块第44号记录 */
/* Dump出该undo块: */
alter system dump datafile 3 block 514;
session_2>select to_char(44,'xx') from dual;
TO_
-----
2c
/* undo块概况信息:rec=44(0x2c)是最后一个记录
irb: 0x2c
irb指的是回滚段中记录的最近未提交变更开始之处,因为是从后往前rollback,如果开始回滚,这是起始的搜索点。
事务的末尾 irb --> undorec.rci --> #repeat# --> until rci=0,rdba!=0 --
--> rdba.rci --> undorec.rci --> #repeat# --> until rci=0,rdba=0 事务的开始
*/
********************************************************************************
UNDO BLK:
xid: 0x0009.006.0000071f seq: 0x287 cnt: 0x2c irb: 0x2c icl: 0x0 flg: 0x0000
Rec Offset Rec Offset Rec Offset Rec Offset Rec Offset
---------------------------------------------------------------------------
0x01 0x1f30 0x02 0x1e80 0x03 0x1dd0 0x04 0x1d18 0x05 0x1c78
0x06 0x1bc8 0x07 0x1b10 0x08 0x1a70 0x09 0x19c0 0x0a 0x194c
0x0b 0x18b4 0x0c 0x17a0 0x0d 0x1738 0x0e 0x16e0 0x0f 0x169c
0x10 0x1640 0x11 0x15cc 0x12 0x1570 0x13 0x151c 0x14 0x1494
0x15 0x1408 0x16 0x13a0 0x17 0x1318 0x18 0x12bc 0x19 0x11d4
0x1a 0x116c 0x1b 0x1114 0x1c 0x108c 0x1d 0x1010 0x1e 0x0fa8
0x1f 0x0efc 0x20 0x0e48 0x21 0x0dcc 0x22 0x0d50 0x23 0x0ce4
0x24 0x0c74 0x25 0x0bc4 0x26 0x0b3c 0x27 0x0ac0 0x28 0x0a58
0x29 0x09d0 0x2a 0x0944 0x2b 0x08dc 0x2c 0x0858
*-----------------------------
* Rec #0x2c slt: 0x06 objn: 73181(0x00011ddd) objd: 73181 tblspc: 4(0x00000004)
* Layer: 11 (Row) opc: 1 rci 0x00
Undo type: Regular undo Begin trans Last buffer split: No
Temp Object: No
Tablespace Undo: No
rdba: 0x00000000Ext idx: 0
flg2: 0
*-----------------------------
uba: 0x00c00202.0287.29 ctl max scn: 0x0000.007e5037 prv tx scn: 0x0000.007e504b
txn start scn: scn: 0x0000.007e557b logon user: 84
prev brb: 12595199 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x03 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: Z
KDO Op code: URP row dependencies Disabled
xtype: XAxtype KDO_KDOM2 flags: 0x00000080 bdba: 0x01000097 hdba: 0x01000092
itli: 2 ispac: 0 maxfr: 4858
tabn: 0 slot: 7(0x7) flag: 0x2c lock: 0 ckix: 191
ncol: 8 nnew: 1 size: 0
Vector content:
col 5: [ 2] c2 1f
session_2>select dump(3000,16) from dual; -- emp.sal 修改前3000
DUMP(3000,16)
------------------
Typ=2 Len=2: c2,1f
slt: 0x06 事务表槽号
objn: 73181(0x00011ddd) objd: 73181 对应数据块对象号。
Tblspc:对应数据块表空间号。
v$transaction查出的uba,指向事务的最后一个操作,和xid对应的dba相同,这是事务回滚的开始位置
UNDO Chain 回滚链 (rdba+rci)
回滚和一致读时需要用到(同一事务中的多次修改,根据Chain链接关联,取得前一个回滚记录的位置)
xid对应的dba块头的irb 指向 回滚链末尾
rci 0x00 代表的就是UNDO Chain,在同一个block内的下一个偏移量
因为这个事务只做了1次dml,所以是0,但这并不能表示这是最后一条记录,rdba如果不为0,代表还没有到事务的开始
上一个dml操作在rdba指向的块的irb对应的undorec里,继续rci不为0就在这个块里回溯上一个dml,直到rci和rdba都是0为止
bdba: 0x01000097 数据块地址
hdba: 0x01000092 数据块所在段的段头块地址
/***********************************************************************************
select dbms_rowid.rowid_object(rowid ) object# ,---> 32bit object#( DATA_OBJECT_ID)
dbms_rowid.rowid_relative_fno( rowid) rfile# ,---> 10bit rfile#
dbms_rowid.rowid_block_number( rowid) block# ,---> 22bit block#
dbms_rowid.rowid_row_number( rowid) row# ---> 16bit row#
from emp a where empno = 7788;
OBJECT# RFILE# BLOCK# ROW#
---------- ---------- ---------- ----------
73181 4 151 7
session_2>variable dba varchar2(30)
session_2>exec :dba := dbms_utility.make_data_block_address(4,151);
PL/SQL procedure successfully completed.
session_2>print dba
DBA
--------------------------------
16777367
session_2>select to_char(16777367,'xxxxxxxxx') from dual;
TO_CHAR(16
----------
1000097
******************************************************************/
dump数据块
alter system dump datafile 4 block 151;
/* ITL */
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0001.010.00000198 0x00c15ab0.0061.12 C--- 0 scn 0x0000.000b6f31
0x02 0x0009.006.0000071f 0x00c00202.0287.2c ---- 1 fsc 0x0000.00000000
bdba: 0x01000097
tab 0, row 7, @0x1e4c
tl: 40 fb: --H-FL-- lb: 0x2 cc: 8
col 0: [ 3] c2 4e 59
col 1: [ 5] 53 43 4f 54 54
col 2: [ 7] 41 4e 41 4c 59 53 54
col 3: [ 3] c2 4c 43
col 4: [ 7] 77 bb 04 13 01 01 01
col 5: [ 2] c2 29
col 6: *NULL*
col 7: [ 2] c1 15
/***************************************************************************************
Xid 0x0009.006.0000071f Xid = Undo.Segment.Number + Transaction.Table.Slot.Number + Wrap
事务序列号: 定位undo段头的事务表的槽位,唯一的代表一个活动的事务
Wrap#列就是V$transcation中的XIDSQN列,表示此回滚槽被重用的次数,
比如0x0009.006.0000071f,上一个同样使用此事务槽的xid=0x0009.006.0000071e,这个xid可能还存在于block中,
但由于和undo9号段头6号槽的wrap#不同,证明这个xid是一个已终结的事务
Uba 0x00c00202.0287.2c Uba = DBA.seq#.rec#
SQL> select to_number('71f','xxx') from dual;
TO_NUMBER('71F','XXX')
----------------------
1823
XIDUSN XIDSLOT XIDSQN
---------- ---------- ----------
9 6 1823
lb: 0x2 表示该行数据被2号事务槽锁定
col 5: [ 2] c2 29
SQL> select dump(4000,16) from dual;
DUMP(4000,16)
------------------
Typ=2 Len=2: c2,29
******************************************************************************************/
/* 在另一会话查询,构造cr块,可从x$bh表中查看 */
SQL> select * from scott.emp where empno = 7788;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- ------------------ ---------- ---------- ----------
7788 SCOTT ANALYST 7566 19-APR-87 3000 20
SQL> select b.segment_name, a.file#, a.dbarfil, a.dbablk, a.class, a.state
from x$bh a, dba_extents b where a.dbarfil = b.relative_fno
and b.owner = 'SCOTT' and b.segment_name = 'EMP'
and a.dbablk >= b.block_id and a.dbablk < b.block_id + b.blocks;
SEGMENT_NA FILE# DBARFIL DBABLK CLASS STATE
---------- ---------- ---------- ---------- ---------- ----------
EMP 4 4 151 1 1
EMP 4 4 151 1 3
EMP 4 4 146 4 3
...
class为4的代表的是段头,class为1,块号为151的为数据块,state为3的代表通过一致性读构造出来的
dump redolog
:set ic
/obj:73181 或者 /0x0009.006.0000071f (用xid)
REDO RECORD - Thread:1 RBA: 0x000003.00011091.0010 LEN: 0x00d8 VLD: 0x05
SCN: 0x0000.007e5561 SUBSCN: 1 11/25/2013 23:29:47
CHANGE #1 TYP:0 CLS:1 AFN:4 DBA:0x01000097 OBJ:73181 SCN:0x0000.007e5555 SEQ:1 OP:11.5 ENC:0 RBL:0
KTB Redo
op: 0x03 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: Z
KDO Op code: URP row dependencies Disabled
xtype: XRxtype KDO_KDOM2 flags: 0x00000080 bdba: 0x01000097 hdba: 0x01000092
itli: 2 ispac: 0 maxfr: 4858
tabn: 0 slot: 7(0x7) flag: 0x2c lock: 0 ckix: 191
ncol: 8 nnew: 1 size: 0
Vector content:
col 5: [ 2] c2 1f
CHANGE #2 TYP:0 CLS:21 AFN:3 DBA:0x00c000a0 OBJ:4294967295 SCN:0x0000.007e5555 SEQ:1 OP:5.11 ENC:0 RBL:0
ktubu redo: slt: 16 rci: 0 opc: 11.1 objn: 73181 objd: 73181 tsn: 4
Undo type: Regular undo Undo type: User undo done Begin trans Last buffer split: No
Tablespace Undo: No
0x00000000
BuExt idx: 0 flg2: 0
/* OP:5.11 是我之前做过一次rollback */
REDO RECORD - Thread:1 RBA: 0x000003.0001109d.0010 LEN: 0x0194 VLD: 0x05
SCN: 0x0000.007e557b SUBSCN: 1 11/25/2013 23:30:46
CHANGE #1 TYP:0 CLS:33 AFN:3 DBA:0x00c00100 OBJ:4294967295 SCN:0x0000.007e5541 SEQ:1 OP:5.2 ENC:0 RBL:0
ktudh redo: slt: 0x0006 sqn: 0x0000071f flg: 0x0012 siz: 132 fbi: 0
uba: 0x00c00202.0287.2c pxid: 0x0000.000.00000000
CHANGE #2 TYP:0 CLS:34 AFN:3 DBA:0x00c00202 OBJ:4294967295 SCN:0x0000.007e5540 SEQ:3 OP:5.1 ENC:0 RBL:0
ktudb redo: siz: 132 spc: 2164 flg: 0x0012 seq: 0x0287 rec: 0x2c
xid: 0x0009.006.0000071f /* xid */
ktubl redo: slt: 6 rci: 0 opc: 11.1 [objn: 73181 objd: 73181 tsn: 4]
Undo type: Regular undo Begin trans Last buffer split: No
Temp Object: No
Tablespace Undo: No
0x00000000 prev ctl uba: 0x00c00202.0287.29
prev ctl max cmt scn: 0x0000.007e5037 prev tx cmt scn: 0x0000.007e504b
txn start scn: 0xffff.ffffffff logon user: 84 prev brb: 12595199 prev bcl: 0 BuExt idx: 0 flg2: 0
KDO undo record:
KTB Redo
op: 0x03 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: Z
KDO Op code: URP row dependencies Disabled
xtype: XAxtype KDO_KDOM2 flags: 0x00000080 bdba: 0x01000097 hdba: 0x01000092
itli: 2 ispac: 0 maxfr: 4858
tabn: 0 slot: 7(0x7) flag: 0x2c lock: 0 ckix: 191
ncol: 8 nnew: 1 size: 0
Vector content:
col 5: [ 2] c2 1f /* 3000 */
CHANGE #3 TYP:0 CLS:1 AFN:4 DBA:0x01000097 OBJ:73181 SCN:0x0000.007e5561 SEQ:1 OP:11.5 ENC:0 RBL:0
KTB Redo
op: 0x01 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: F xid: 0x0009.006.0000071f uba: 0x00c00202.0287.2c
KDO Op code: URP row dependencies Disabled
xtype: XAxtype KDO_KDOM2 flags: 0x00000080 bdba: 0x01000097 hdba: 0x01000092
itli: 2 ispac: 0 maxfr: 4858
tabn: 0 slot: 7(0x7) flag: 0x2c lock: 2 ckix: 191
ncol: 8 nnew: 1 size: 0
Vector content:
col 5: [ 2] c2 29 /* 4000 */
/*
CHANGE #1 OP:5.2 Update rollback segment header 对undo段头块的修改
CHANGE #2 OP:5.1 Undo block or Undo segment header 对undo数据块的修改
CHANGE #3 OP:11.5 Update Row Piece 对数据块的修改
*/
事务的开始:
(1) 首先当一个事务开始时,需要先绑定一个可用的rollback segment
(2) 在回滚段事务表上分配一个事务槽
(3) 从rollback segment中分配undo block
(4) 在数据块头部获取一个ITL事务槽,该事务槽指向回滚段头的事务槽
(5) 在修改数据之前,需要记录前镜像信息,这个信息以UNDO RECORD的形式存储在回滚段中,回滚段头事务槽指向该记录。
(6) 锁定修改行,修改行锁定位(lb-lock byte)指向ITL事务槽。
(7) 数据修改可以进行。
现在若 commit;
段头事务表
6号事务槽state变成了9,cflags变为00,uel变成了无限大(ffff),scn变成了提交时的scn
undo block不会变化
redo 增加一条记录 OP:5.4 Commit transaction (transaction table update)
--引用牛人总结...
commit时:
(1) Oracle先去改这个transaction所对应的undo segment header中slot的状态
(2) 改完状态后再flush log buffer
COMMIT时:
得到一个SCN值
使用得到的SCN更新事务表中的槽位
在redo log buffer中创建一条commit记录
将redo log buffer刷新到磁盘上的在线日志文件
释放表和行上的锁(may cause delayed block cleanout)
/* undo segment的使用 */
1. 事务表:
回滚段中第一个块是回滚段头,它控制着回滚段的改变数据的写。在此回滚段头中,有一个事务表,每一个活动的事务,在各回滚段事务表中都要占一行。
当还原表空间空间足够时,Oracle倾向于让每个事务各占一个回滚段。否则,会让多个事务占用一个回滚段。每回滚段的第一个块,又被称为回滚段头,通常被事务表占用。事务表中保存本回滚段中的所有事务信息。默认的事务表的数量根据块大小而不同,此数值不可增加,它根据块大小的不同而不同。事务表中的每一行,又称为一个事务槽(slot)。
2. 如果回滚段中有多个事务,回滚段中的区会被多个事务占用,但任一回滚块中只能有一个事务。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/28859270/viewspace-1061083/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/28859270/viewspace-1061083/