Phone:18180207355 提供专业Oracle&MySQL数据恢复、性能优化、迁移升级、紧急救援等服务

前几天跟lunar讨论问题,他提到关于数据库中段头block损坏的恢复以及假如出现位图block损坏等的情况恢复,
如何在没有备份的情况下,那就是个灾难,如果表小还好办,我们可以通过基于rowid等方式去扫描把数据抽取cats
出来,或者你可以使用odu/dul等数据抽取工具。 就像lunar提到的曾经遇到的一个case是有个表的段头坏了,但是
该表非常巨大,超过300g,在这种情况下,如果没有备份,处理起来就非常的麻烦了,虽然这样的情况很少见,但
我这里还是根据她的要求来研究下段头和位图block的结构,以便于我们在极端情况下用bbed等工具去直接修复.

该段头的dump信息如下:

从上面我们可以看到,对于段头,里面的信息其实很简单,我们可以使用dbms包去转换dba地址为file、block号,如下:

如下是针对段头block的dump信息:

++++++++alter system dump datafile 2 block 35

如下是段头block的每个offset的含义,这里我只是列举了大部分相对重要的offset:

offset 1: 23 表示block type 类型,23表示表段头,0x0b表示datafile header block类型.
offset 2: a2 表示block格式类型,这个跟普通的block格式类型一样。
offset 5~8: 23008000 表示该block的rdba地址,可以进行手工进行转换。
offset 9~14: f2085e00.0000 表示该block的scn值.
offset 15: 01 表示sequences号,是用于计算tail值用的.
offset 16: 04 表示flag值,针对block的flag值有如下几种属性:

#define KCBHFNEW 0x01 /* new block – zeroed data area            */
#define KCBHFDLC 0x02 /* Delayed Logging Change advanced SCN/seq */
#define KCBHFCKV 0x04 /* ChecK Value saved – block xor’s to zero */
#define KCBHFTMP 0x08 /* Temporary block                         */

offset 17~18: 1547 表示block的check值,该值无所谓,如果用bbed进行修改后,可以sum apply会重新校验生成。
offset 37: 15 表示该段头信息所包含的extent个数,转换为10进制为21,即包含21个extent。
offset 41~42:0003,由于我这里字节序是32位,bbed看到的信息是反的,所以应该是0300,转换后为768,表示
这个段所包含的block个数,即段的大小,单位block

offset 45~46:  9c0a 表示extent header所在的offset,转换为10进制后为2716.

offset 49: 14 表示高水位标记的extent号.
offset 53:51 对于段头dump的blk#值,应该是值的block号
offset 57: 80 表示该extent所包含的block个数。     (offset 49~57 对应的都的高水位标记)
offset 60~64:  5a068000 表示表水位标记的rdba地址.

offset 69: 14 表示mapblk 对于的offset,居然含义不太清楚。
offset 76~80:d1020000 表示高水位标记下的blocks总数.

offset 92: 14 表示低水位标记的extent号.
offset 104~108: 5a068000 表示低水位标记的rdba地址.
offset 120~124: 5a068000 表示一级位图block的High HWM block rdba地址
offset 125~128: 5a068000 表示一级位图block的Low HWM block rdba地址
offset 213~214:2000  表示block size大小.
offset 221~224: 34140000 表示L2 Array start offset.
offset 229~232: 22008000 表示二级位图L2 Hint for inserts rdba地址.
offset 336~240: 0a068000 表示Last Level 1 BMB rdba地址。
offset 241~244:22008000 表示Last Level II BMB rdba地址.
offset 257~258: 46e8      表示object id号.
offset 261~264: 00000010  表示map header 的flag地址,段头的dump都是这个值.
offset 8189~8192:08F22301 表示该block的tail值。 该值属性为SCN bas+type+scn seq

中间还有一些Extent Map和Auxillary Map 信息,不多说了。

我想,了解上述的段头block的信息后,出现段头坏的情况,用bbed足以修复了。
接下来我们来看下位图block的结构,这里先说一级位图block.如下是一级位图block的dump信息:

+++++++ alter system dump datafile 2 block 1546

offset 1: 20 表示block type类型,20表示一级位图block,21表示二级位图block,22表示三级位图block。
offset 2:a2 表示block格式类型,这个跟普通的block格式类型一样
offset 5~8: 0a068000 表示该block的rdba地址.
offset 9~12: f0085e00 表示scn值.
offset 15: 02 表示sequence值
offset 16: 04 表示flag值.
offset 17~20: 396a0000 表示block 的check 值.
offset 81~84: ffffffff 表示Extent Map Block Offset值,这里该位图block没有extent map,所以默认为最大值也就是8个f.
offset 85: 2f 表示unformatted block的个数. 即高水位上的block个数。
offset 92: 40 表示该位图block所对应的data block个数.
offset 117: 11 表示该位图block所对应的parent dba的offset值.
offset 145~148: 22008000 表示该位图block的parent block dba地址。
offset 165~168:5a068000 表示Highwater 标记dba地址.
offset 181~184: d1020000 表示高水位标记下的block总数.
offset 193~196: 46e80000 表示object id号.
offset 205~208:49068000 表示该位图block所对应的数据块dba ranges地址的起始值。

最后我们来看下二级位图block的结构:
Start dump data blocks tsn: 6 file#: 2 minblk 34 maxblk 34
buffer tsn: 6 rdba: 0x00800022 (2/34)
scn: 0x0000.0061c551 seq: 0x03 flg: 0x04 tail: 0xc5512103
frmt: 0x02 chkval: 0x6c9d type: 0x21=SECOND LEVEL BITMAP BLOCK
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x0D0D9800 to 0x0D0DB800
D0D9800 0000A221 00800022 0061C551 04030000  [!…”…Q.a…..]
D0D9810 00006C9D 00000000 00000000 00000000  [.l…………..]
D0D9820 00000000 00000000 00000000 00000000  […………….]
Repeat 1 times
D0D9840 00000000 00000000 00000000 00800023  […………#…]
D0D9850 00000064 00000001 00000062 00000000  [d…….b…….]
D0D9860 00000000 00000000 0000E846 00000001  [……..F…….]
D0D9870 00000000 00800021 00010001 00800031  [….!…….1…]
……..
D0D9B90 00010001 00000000 00000000 00000000  […………….]
D0D9BA0 00000000 00000000 00000000 00000000  […………….]
Repeat 452 times
D0DB7F0 00000000 00000000 00000000 C5512103  [………….!Q.]
Dump of Second Level Bitmap Block
number: 100     nfree: 1       ffree: 98     pdba:     0x00800023
Inc #: 0 Objd: 59462
opcode:0
xid:
L1 Ranges :
——————————————————–
0x00800021  Free: 1 Inst: 1
0x00800031  Free: 1 Inst: 1
0x00800041  Free: 1 Inst: 1
0x00800051  Free: 1 Inst: 1
………

可以看到,二级位图block的结构也不复杂,除了头部的信息跟前面的一级位图block基本上一致外,后面就是一个
对应的一级位图block的dba 范围列表。所以这里我就不再相信去描述二级位图block的每个offset的具体含义了。

同理,三级位图block的结构也是类似的,不同的是除开前面的头部信息外,后面跟着的是对应的二级位图block的范围列表信息。
事实上,对于8k的block size,要出现三级位图block是非常困难的,一般情况下大家根本遇不到的。

最后简单总结下:

1. 针对段头损坏的情况,如果有备份,可以使用rman的blockrecover,如果没有备份,那么就很悲剧了。
2. 如果位图block损坏,即使没有备份,也可以使用基于rowid的方式进行cats抽取数据。
3. 针对上面的2种情况,都可以使用odu、dul等工具抽取数据。
4. 如果问题不复杂的话,在备份数据文件后,你可以使用bbed去修复上面的块损坏,不过这个要慎重。
5. 我这里是32位,bbed dump是反的,另外我是从offset 1开始(图方便计算),大家自己算的时候减1个offset即可.

6. 本来不计划发出来的,想想还是发出来,免得大家说我藏着掖着,但是注意,出问题了,我概不负责哦!!!
最后是贴个模拟段头损坏的情况:

使用使用bbed修改block前面的部分即可,dba地址我们可以转换进行反推,如下:

    分享到:
18180207355
加Q咨询