[English]
作者:
fuyuncat
来源:
www.HelloDBA.com
事务和数据块
这里主要想通过试验来推断Oracle的事务在数据块(Oracle中存储的最小单位)上一些微观操作,以便于更好的理解Oracle的事务控制、一致性处理及锁冲突。
创建测试表:
SQL> create table t_multiver (a number, b number);Table created.SQL> insert into t_multiver values (1,1);1 row created.SQL> insert into t_multiver values (2,2);1 row created.SQL> insert into t_multiver values (3,3);1 row created.SQL>SQL> commit;Commit complete.
首先,看一下数据块上和记录有关的标示,dump一个数据块看看:
SQL> alter system dump datafile 5 block 50816;System altered.
看看Dump出来的内容:
Block header dump: 0x0140c70fObject id on Block? Yseg/obj: 0xe46c csc: 0x00.a4462b75 itc: 2 flg: E typ: 1 - DATAbrn: 0 bdba: 0x140c709 ver: 0x01 opc: 0inc: 0 exflg: 0Itl Xid Uba Flag Lck Scn/Fsc0x01 0x0008.020.0000192f 0x0080051a.059f.34 --U- 3 fsc 0x0000.a4462b7a0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000data_block_dump,data header at 0x9f75664===============tsiz: 0x1f98hsiz: 0x18pbl: 0x09f75664bdba: 0x0140c70f76543210flag=--------ntab=1nrow=3frre=-1fsbo=0x18fseo=0x1f7davsp=0x1f65tosp=0x1f650xe:pti[0] nrow=3 offs=00x12:pri[0] offs=0x1f8f0x14:pri[1] offs=0x1f860x16:pri[2] offs=0x1f7dblock_row_dump:tab 0, row 0, @0x1f8ftl: 9 fb: --H-FL-- lb: 0x1 cc: 2col 0: [ 2] c1 02col 1: [ 2] c1 02tab 0, row 1, @0x1f86tl: 9 fb: --H-FL-- lb: 0x1 cc: 2col 0: [ 2] c1 03col 1: [ 2] c1 03tab 0, row 2, @0x1f7dtl: 9 fb: --H-FL-- lb: 0x1 cc: 2col 0: [ 2] c1 04col 1: [ 2] c1 04end_of_block_dumpEnd dump data blocks tsn: 5 file#: 5 minblk 50959 maxblk 50959注意红色黑体部分和Interested Transaction Slot (ITS) 部分。
CSC:即Cleanout SCN,最后一次对该数据块进行Cleanout的SCN。
Itc: Itl count。Itl的数量。看到下面的Itl列表中有两条记录,所以是2。
Itl:Interested Transaction List。直译过来就是感兴趣的事物列表。也就是对该数据块产生影响的事物。对应的数字是序列号。
Xid:Transaction ID。事务ID号。在相应回滚段的事物信息表中对应唯一一条记录。Uba:Undo Block Address。回滚数据块地址,该地址对应了该事务在回滚段中记录的回滚数据的地址。
分解该地址:
0x0080051a.059f.34第一段是回滚数据块的地址,包括回滚段文件号和数据块号;第二段是回滚序列号;第三段是回滚记录号。
Flag:事务标志位。这个标志位就记录了这个事务的操作,各个标志的含义分别是:
C--- = transaction has been committed and locks cleaned out
-B-- = this undo record contains the undo for this ITL entry
--U- = transaction committed (maybe long ago); SCN is an upper bound
---T = transaction was still active at block cleanout SCNScn/Fsc:快速提交(Fast Commit Fsc)的SCN或者Commit SCN。
每条记录中的行级锁对应Itl条目lb,对应于Itl列表中的序号,即那个事务在该记录上产生的锁。
回滚段
下面再看看回滚段中是如何记录的:
更新数据(数据更新前b=115):
SQL> conn demo/demoConnected.SQL> alter system flush buffer_cache;System altered.SQL>SQL> update t_multiver set b=116 where a=1;1 row updated.
查看事务信息:
select UBAFIL, UBABLK, UBASQN, UBAREC from v$transaction;11 80 886 16
UBAFIL:回滚段文件号;
UBABLK:数据块号;
UBASQN:回滚序列号;
UBAREC:回滚记录号。
这些数据就对应了数据块中的Uba。
也可以通过以下方式从数据块的Uba中获取到回滚段这些信息:
0x02c00050.0376.10
0376即回滚序列号,10即回滚记录号。它们都是16进制。
下面获取文件号和数据块号:
SQL> set serveroutput onSQL> declare2 v_file number;3 v_block number;4 begin5 v_file := dbms_utility.data_block_address_file(to_number('02c00050','xxxxxxxx'));6 v_block := dbms_utility.data_block_address_block(to_number('02c00050','xxxxxxxx'));7 dbms_output.put_line('file id: '||v_file);8 dbms_output.put_line('block id: '||v_block);9 end;10 /file id: 11block id: 80PL/SQL procedure successfully completed.
Dump出数据块和回滚块:
SQL> alter system dump datafile 5 block 50959;System altered.SQL> conn demo/demoConnected.SQL>SQL> alter system dump datafile 11 block 80;System altered.
数据块dump信息:
Block header dump: 0x0140c70fObject id on Block? Yseg/obj: 0xe46c csc: 0x00.a4a39eda itc: 2 flg: E typ: 1 - DATAbrn: 0 bdba: 0x140c709 ver: 0x01 opc: 0inc: 0 exflg: 0Itl Xid Uba Flag Lck Scn/Fsc0x01 0x000f.006.00000a14 0x02c00050.0376.10 ---- 1 fsc 0x0000.000000000x02 0x0012.02a.0000096d 0x02c00088.0355.09 C--- 0 scn 0x0000.a4a39bd8
回滚块信息:
********************************************************************************UNDO BLK:xid: 0x000f.006.00000a14 seq: 0x376 cnt: 0x10 irb: 0x10 icl: 0x0 flg: 0x0000Rec Offset Rec Offset Rec Offset Rec Offset Rec Offset---------------------------------------------------------------------------0x01 0x1f68 0x02 0x1ed0 0x03 0x1e50 0x04 0x1d94 0x05 0x1d2c0x06 0x1cd4 0x07 0x1c7c 0x08 0x1c24 0x09 0x1ba4 0x0a 0x1b240x0b 0x1a8c 0x0c 0x1a0c 0x0d 0x1998 0x0e 0x1918 0x0f 0x187c0x10 0x17e8... ...*-----------------------------* Rec #0x10 slt: 0x06 objn: 58476(0x0000e46c) objd: 58476 tblspc: 5(0x00000005)* Layer: 11 (Row) opc: 1 rci 0x00Undo type: Regular undo Begin trans Last buffer split: NoTemp Object: NoTablespace Undo: Nordba: 0x00000000*-----------------------------uba: 0x02c00050.0376.0f ctl max scn: 0x0000.a4a39a02 prv tx scn: 0x0000.a4a39a16txn start scn: scn: 0x0000.a4a39eda logon user: 35prev brb: 46137423 prev bcl: 0KDO undo record:KTB Redoop: 0x04 ver: 0x01op: L itl: xid: 0x0014.022.00000776 uba: 0x02c000a5.029b.32flg: C--- lkc: 0 scn: 0x0000.a4a39a3eKDO Op code: URP row dependencies Disabledxtype: XAxtype KDO_KDOM2 flags: 0x00000080 bdba: 0x0140c70f hdba: 0x0140c70bitli: 1 ispac: 0 maxfr: 4858tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 8ncol: 2 nnew: 1 size: 0Vector content:col 1: [ 3] c2 02 10End dump data blocks tsn: 11 file#: 11 minblk 80 maxblk 80
仔细比较一下两个dump文件,数据块的事务回滚信息就很清楚了:
在数据块中:
对象号是
0xe46c,即十进制的58476;Xid是
0x000f.006.00000a14;Uba是
0x02c00050.0376.10。即11号文件的第80个数据块,回滚序列号是0x0376,回滚记录号是0x10。
回滚数据块中:
Xid是
0x000f.006.00000a14,与数据块中Itl中的Xid对应;
seq: 0x376,与数据块的Uba中吻合;
cnt: 0x10,此回滚数据块中有16条回滚记录,根据Uba,我们要找的是第16条记录;找到第16条回滚记录
Rec #0x10:
slt: 0x06,即第6个slot。
objn和objd是58476,与数据块中的对象号相同;
tblspc是5,也就是对象t_multiver所在的表空间号;
Layer即层次,这是一次对记录的更新,所以是11 (Row);
Undo type: Regular undo Begin trans,我们这个事务是刚开始时,在没有提交或回滚时dump出来的;
Temp Object: No,这个对象不是临时对象。
在*-----------------------------以下的就是记录的旧数据镜像了:记录了它的Uba、最大控制Scn(
ctl max scn)、上一次事务scn(prv tx scn)等信息,如果我们做了事务开始前的数据dump,就能一一找到对应关系了。最下面就是修改前的数据记录了。