update之后:
tab 0, row 4, @0x2a7 tl: 121 fb: --H-FL-- lb: 0x2 cc: 4 col 0: [ 2] c1 0a col 1: [ 2] c1 06 col 2: [10] 59 59 59 59 59 59 59 59 59 59 col 3: [100] 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30我们可以看到col2长度变成了10,是10个59(Y的十六进制ASCII码是59),同时我们看到行地址由@0x1d3f变成了@0x2a7,说明这一行的空间容不下新增的数据,换了一个地方。(检查行目录也能发现这一点)同时,我们能看到lb(lock byte)由0x0变成了0x2,表明这条记录被该块事务槽列表中的第二个事务槽所标识的事务锁定。事务槽可以在块首部看到。
下面,看第5条数据在redo里面保存的是什么(怎么保证数据的重做),在文件里面搜索 tabn: 0 slot: 4(0x4) flag: 0x2c lock: 2, 我们会找到这么一段描述
CHANGE #6 TYP:0 CLS:1 AFN:1 DBA:0x004161c9 OBJ:77125 SCN:0x0000.002796b6 SEQ:2 OP:11.5 ENC:0 RBL:0 KTB Redo op: 0x02 ver: 0x01 compat bit: 4 (post-11) padding: 0 op: C uba: 0x00c0055a.0123.27 KDO Op code: URP row dependencies Disabled xtype: XA flags: 0x00000000 bdba: 0x004161c9 hdba: 0x004161c8 itli: 2 ispac: 0 maxfr: 4863 tabn: 0 slot: 4(0x4) flag: 0x2c lock: 2 ckix: 50 ncol: 4 nnew: 1 size: 4 col 2: [10] 59 59 59 59 59 59 59 59 59 59这描述的是一个改变世界,我们看第6行 op code:是URP(更新行片),第七行我们可以看到更新的块地址bdba和所在段的地址hdba。
第八行itli: 2 表明执行更新操作的事务正在使用第二个事务槽,跟数据块里面看到的一致。
第九行tabn: 0 slot: 4 表明我们在更新第一张表(一个块可能存储多个表的数据)的第5条记录。
最后两行,我们可以看出这条记录有4列(nclo:4),修改了一列(nnew:1),长度增加了4(size:4).并将第3列的值改成了YYYYYYYYYY。(保存了修改后的数据,方便重做)
接下来,看第5条数据在undo里面怎么保存的(怎么保证数据的回退),在文件里面搜索tabn: 0 slot: 4(0x4) flag: 0x2c,我们会找到如下一段描述:
*----------------------------- * Rec #0x27 slt: 0x04 objn: 77125(0x00012d45) objd: 77125 tblspc: 0(0x00000000) * Layer: 11 (Row) opc: 1 rci 0x26 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 compat bit: 4 (post-11) padding: 0 op: C uba: 0x00c0055a.0123.25 KDO Op code: URP Disabled row dependencies xtype: XA flags: 0x00000000 bdba: 0x004161c9 hdba: 0x004161c8 itli: 2 ispac: 0 maxfr: 4863 tabn: 0 slot: 4(0x4) flag: 0x2c lock: 0 ckix: 50 ncol: 4 nnew: 1 size: -4 col 2: [ 6] 78 78 78 78 78 78主要关注下面的六行数据,其实跟前面redo里面的数据差不多,就是size=-4,col2变成了6个78(x的十六进制ASCII码是78)。(保证数据能够回去以前的版本)
最后,我们可以在转储的redo里面寻找undo块改变的描述,文件里面搜索tabn: 0 slot: 4(0x4) flag: 0x2c lock: 0,我们会找到如下一段描述:
CHANGE #11 TYP:0 CLS:36 AFN:3 DBA:0x00c0055a OBJ:4294967295 SCN:0x0000.002796b6 SEQ:4 OP:5.1 ENC:0 RBL:0
ktudb redo: siz: 92 spc: 4078 flg: 0x0022 seq: 0x0123 rec: 0x27
xid: 0x000a.004.00000467
ktubu redo: slt: 4 rci: 38 opc: 11.1 objn: 77125 objd: 77125 tsn: 0
Undo type: Regular undo Undo type: Last buffer split: No
Tablespace Undo: No
0x00000000
KDO undo record:
KTB Redo
op: 0x02 ver: 0x01
compat bit: 4 (post-11) padding: 0
op: C uba: 0x00c0055a.0123.25
KDO Op code: URP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x004161c9 hdba: 0x004161c8
itli: 2 ispac: 0 maxfr: 4863
tabn: 0 slot: 4(0x4) flag: 0x2c lock: 0 ckix: 50
ncol: 4 nnew: 1 size: -4
col 2: [ 6] 78 78 78 78 78 78 第五行,代表这是一个undo块改变的描述,我们可以看到倒数几行跟undo里面的数据非常相似,因为这里记录的就是undo块的改变。
自此,我们基本上可以看清楚oracle是怎么描述数据的改变,然后才去真正去改变数据的。