oracle提交6,Oracle数据库特种恢复技术(六)—undo篇

本帖最后由 ubotutwin 于 2012-2-1 10:06 编辑

Oracle数据库特种恢复技术(六)—undo篇

作者:谢浩

xid: 0x0009.016.00003529  seq:0x131e cnt: 0xf   irb: 0xf   icl: 0x0  flg: 0x0000

Rec Offset      Rec Offset      Rec Offset      Rec Offset      Rec Offset

---------------------------------------------------------------------------

0x01 0x1f70     0x02 0x1f18     0x03 0x1ec4     0x04 0x1e40     0x05 0x1dd8

0x06 0x1d6c     0x070x1be0     0x08 0x1b5c     0x09 0x1af4     0x0a 0x1a88

0x0b 0x18fc     0x0c0x1860     0x0d 0x180c     0x0e 0x17b8     0x0f 0x1764

……………………………省略中间无关内容………………………………………

*-----------------------------

* Rec #0xf  slt: 0x16  objn: 76138(0x0001296a)  objd: 76138 tblspc: 4(0x00000004)

*       Layer:  11 (Row)  opc: 1   rci 0x0eUndo type:  Regular undo   Last buffer split:  No

Temp Object:  No

Tablespace Undo:  No

rdba: 0x00000000

*-----------------------------

KDO undo record:

KTB Redo

op: 0x03  ver: 0x01

op: Z

KDO Op code: URP row dependencies Disabled

xtype: XA flags:0x00000000  bdba: 0x01007803  hdba: 0x01006e83itli: 2  ispac: 0  maxfr: 4858

tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 0

ncol: 13 nnew: 1 size: 1

col  1: [ 4]  54 45 53 54

End dump data blocks tsn: 1 file#: 2 minblk 1163 maxblk 1163

dd输出:

00000000h: 02 A2 00 00 8B 04 80 00 51 1E 54 01 00 00 04 04 ;.?.?.Q.T.....

00000010h: 44 A0 00 00 09 00 16 00 29 35 00 00 1E 13 0F 0F ;D?.....)5......

00000020h: 00 00 E8 1F 70 1F 18 1F C4 1E 40 1E D8 1D 6C 1D ;..?p...?@.?l.

00000030h: E0 1B 5C 1B F4 1A 88 1A FC 18 60 18 0C 18 B8 17 ;?\.???`...?

00000040h: 64 17 F4 18 98 18 08 18 A4 17 48 17 B8 16 54 16 ;d.??..?H.?T.

00000050h: F8 15 68 15 04 15 A8 14 18 14 B4 13 58 13 C8 12 ;?h...?..?X.?

00000060h: 64 12 08 12 78 11 14 11 B8 10 28 10 C4 0F 68 0F ;d...x...?(.?h.

00000070h: D8 0E 74 0E 18 0E 88 0D 24 0D C8 0C 38 0C D4 0B ;?t...?$.?8.?

00000080h: 78 0B E8 0A 84 0A 28 0A 98 09 34 09 D8 08 48 08 ;x.??(.?4.?H.

00000090h: E4 07 88 07 F8 06 94 06 38 06 A8 05 44 05 E8 04 ;????8.?D.?

000000a0h: 58 04 F4 03 98 03 08 03 A4 02 48 02 B8 01 54 01 ;X.??..?H.?T.

000000b0h: F8 00 93 04 B0 04 CD 04 EA 04 07 05 24 05 41 05 ;?????..$.A.

000000c0h: 5E 05 7B 05 98 05 B5 05 D2 05 EF 05 0C 06 29 06 ;^.{.????..).000000d0h: 46 06 63 06 80 06 9D 06 BA 06 D7 06 F4 06 11 07 ; F.c.??..

000000e0h: 2E 07 4B 07 68 07 85 07 A2 07 BF 07 DC 07 F9 07 ;..K.h.?????

000000f0h: 16 08 33 08 50 08 6D 08 8A 08 A7 08 C4 08 E1 08 ;..3.P.m.????

00000100h: FE 08 1B 09 38 09 55 09 72 09 8F 09 0A 00 18 00 ;?..8.U.r.?....……………………………省略…………………………………

在每个undo block的offset 34位置保存了一个重要的数据结构,由于没有相关文档,我暂时称之为undo record list其对应bbed中的ktubhidx数组,其格式为每两个字节记录一个undo record的offset。在该数组之前的offset 30位置的ktubhcnt变量记录了该数组中最后一个元素的下标。由于我们在恢复数据的过程中可以直接获得事务的uba,结合该list就能定位一个事务的undo链表的header。

从先前update语句后的datablock中的itl可以获得该活动事务对应的uba的rec一项为0x0f,因此在offset  34+2*14=62的位置就可以得到该条undorecord的物理地址,细心的读者可能看出我上面贴出的dd输出和dump输出数据不符,这是由于这个列表的第一项的值1fe8是固定指向块最后四个字节的,也就是块的校验信息。这里,该记录的偏移量为0x1764,这个地址还要加上20的基本偏移量(kcbh结构体的长度)就可以获得该条undo record的物理地址:6008.

观察二进制文件6008位置:

00001778h: 0C 00 18 00 08 00 1D 00 02 00 04 00 6A 29 01 00 ;............j)..

00001788h: 6A 29 01 00 04 00 00 00 00 00 00 00 0B 01 16 0E ;j)..............

00001798h: 00 00 29 35 03 01 C0 00 08 00 FF FF 03 78 00 01 ;..)5..?...x..000017a8h: 83 6E 00 01 FA 12 05 01 02 00 00 00 2C 00 00 00 ; 僴..?......,...

000017b8h: 00 00 0D 01 01 00 00 00 00 00 C5 28 01 00 00 00 ;..........?....

000017c8h: 54 45 53 54 0C 00 18 00 08 00 1D 00 02 00 04 00 ;TEST............

000017d8h: 6A 29 01 00 6A 29 01 00 04 00 00 00 00 00 00 00 ;j)..j)..........

000017e8h: 0B 01 16 0D 00 00 29 35 03 01 02 C1 03 03 C0 0D ;......)5...?.?000017f8h: F3 77 00 01 83 6E 00 01 FA 12 05 01 02 00 00 00 ; 體..僴..?......

00001808h: 2C 00 00 00 3C 00 0D 01 01 00 00 00 00 D6 84 00 ;,...<........>

00001818h: 01 00 28 1E 54 45 53 54 0C 00 18 00 08 00 1D 00 ;..(.TEST........

00001828h: 02 00 04 00 6A 29 01 00 6A 29 01 00 04 00 00 00 ;....j)..j)......

00001838h: 00 00 00 00 0B 01 16 0C 00 00 29 35 03 01 BF 74 ;..........)5..縯

00001848h: 00 00 00 00 37 75 00 01 83 6E 00 01 FA 12 05 01 ;....7u..僴..?..

00001858h: 03 00 00 00 2C 00 00 00 53 00 0D 01 01 00 00 00 ;....,...S.......

00001868h: 00 00 05 00 01 00 00 00 54 45 53 54 0C 00 48 00 ;........TEST..H.00001878h: 20 00 1D 00 02 00 04 00 6A 29 01 00 6A 29 01 00 ;  .......j)..j)..

00001888h: 04 00 00 00 00 00 00 00 0B 01 16 00 08 04 01 00 ;................00001898h: 8B 04 80 00 1E 13 08 00 A1 1A 54 01 00 00 00 00 ; ?...?T.....

000018a8h: E9 1A 54 01 00 00 00 00 04 00 11 00 51 1E 54 01 ;?T.........Q.T.000018b8h: 00 00 2E 93 20 0C 80 00 00 00 00 00 05 00 00 00 ; ...?..........

000018c8h: 04 01 00 00 00 00 00 00 09 00 2D 00 FC 31 00 00 ;..........-.?..000018d8h: C7 0B 80 00 4E 12 38 00 00 80 00 00 9A 8E 40 01 ; ?.N.8..殠@.

000018e8h: 84 6E 00 01 83 6E 00 01                         ; 刵..僴..

一条undo record是由多条undo明细组成的,Oracle数据库undorecord的开始部分,是一个内部undo明细的长度的列表,这里我姑且称之为undo disc length list。而这个列表的最前面两个字节,记录的就是该列表本身的长度,这里的值为:0c  00。这里需要注意的是,undo内部长度记录的和上个章节所接受的redo记录有一个共同特点,就是实际长度需要向上对其到4的整倍数。0C 00 18 00 08 00 1D 00 02 00 04 00这一段,就是该undo record的“明细长度列表”。

第一条长度为0x18的明细记录的是undorecord的基本信息,如该条undo record所对应的objid:6A 29 01 00 6A 29 01 00 04 00 00 00 00 00 00 00 0B 01 16 0E 00 00 2935,其中:6A 29 01 00对应dump文件的objn;6A 29 01 00对应dump文件的objd;04 00 00 00对应dump文件的tblspc;0B对应dump文件的Layer;01对应dump文件的opc;16意义不明;0E对应dump文件的rci,这个变量非常重要,记录了该事务的变更记录的下体条的rec信息,也就是指向事务中下一个undo record的指针,如果一个事务占用了超过一个undo block,那么还要结合rdba中上一个undo record的dba来进行定位。最后两位29 35意义不明。

第二条长度为0x08的明细记录对应dump文件中的ktb部分: 03 01 C000 08 00 FF FF,其中03对应dump文件的op;01对应dump文件的ver。其后6个字节意义不明。这里需要注意的是,如果一条undo record是该事务的undo链上的第一条undo record,那么该条undo record的这一部分还要多出itl、uba、flg、lkc、scn等信息,相应的这一部分明细记录的长度也会增加。

第三条长度为1D的明细记录对应的是该变更的具体操作记录: 03 78 00 01 83 6E 00 01 FA 12 05 01 02 00 00 00 2C 00 00 00 00 000D 01 01 00 00 00 00 00 C5 28。0x1D对应10进制的29,需要向上对其到32。其中03 78 00 01对应dump文件中的bdba;83 6E 00 01对应dump文件中的hdba;FA 12对应dump文件中的maxfr;其后的05 对应上一篇中的redo 操作代码中layer为11的opcode,这里的05,对应的就是11.05的redo操作:Update Row Piece(这一部分困扰了我很久,将增删改三种操作的二进制文件放在一起对比观察才有所得);其后的01对应dump文件的ver;其后的02 00对应dump文件的itli;其后的00 00对应dump文件的ispac;其后的2C 00对应dump文件的flag;其后的00 00对应dump文件的tabn;其后的00 00对应dump文件的slot;

到这里是一个非常重要的标志,slot对应的是数据块里的行号,因此,到这里已经可以定位变更的是哪一行数据了。

其后的0D对应dump文件的ncol;其后的01对应dump文件的nnew;其后的01 00对应dump文件的size;其后的00 0000意义不明。

第四条长度为02的明细记录整体意义不明。

最后一条长度为04的明细记录,就是被更新字段的前镜像值: 5445 53 54SQL> select dump('TEST',1016) from dual;

DUMP('TEST',1016)

-----------------------------------------------

Typ=96 Len=4 CharacterSet=ZHS16GBK:54,45,53,54

可见,其与之前语句中的值完全相符。

以上分析的是一次事务在同一个块中只涉及到一行的情况,如果涉及到多行,会在第三条和最后一条明细记录上有差别:根据分析,第三条明细记录实际上应该是一个数组,每一个被更改的行在其中占用28(或29)字节存储。最后一条明细记录在只变更一行时直接存储字段的前镜像值,在一个undo record中记录多行数据时记录的是和data block一样的格式即:字段长度1 字段值1 字段长度2 字段值2。。。。。依此类推。如果是一次更新一行的多个字段,也会在第三条明细记录上体现。

总体来讲oracle软件对于Undo 的存储和处理方式与redo比较相近,这里顺便回答一个之前网友提出的问题--为什么redo以不受oracle管理的文件方式存储,而undo以标准oracle数据块的方式存储?其实这是因为,redo只在oracle需要恢复时才用到,而这时oracle系统可能还没有正式加载完全部表,而undo在数据库运行过程中经常要被用到,所以oracle可以用同一个方式处理数据块和undo块。

在oracle最重要的data、redo、undo三种数据中,Undo的处理逻辑可以说是最复杂的,在对undo的解析过程中也对oracle回滚事务、构造一致性读取的方式有了非常深刻的理解。

至此已经可以解出oracle undo的数据了,oracle特种恢复技术的主体部分也到此结束了,下一步是对整个分析过程,及在该过程中的所得做一总结。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值