Some lob internal
Posted: December 12, 2011 | Author: Cui Hua | Filed under: Oracle | Tags: lob internal | Leave a comment »这篇文章源于我昨天和今天跟老熊的无数次电话交流,老熊是极其强悍的,每次我跟他讨论完问题后,我对某个知识点的认识都能得到质的提高,再次感谢老熊!
1、402e里这么提到——When a LOB is stored out-of-line in an “enable storage in row” LOB column between 36 and 84 bytes of control data remain in-line in the row piece. 这里的control data到底是指什么?
答:这里的control data就是指的12个chunk的起始RDBA。
col 0: [ 2] c1 02
col 1: [ 7] 63 75 69 68 75 61 31
col 2: [84]
00 54 00 01 01
00 00 36
02 85 01 00 03 0d 01 00 03 15 01 00 03 1d 01 00 03 25 01 00 03 2d 01 00 03
35 01 00 03 3d 01 00 03 45
这里的lob id是00 00 00 01 00 00 00 01 1e b9,这里的第36个byte到第84个byte就是12个RDBA,第1个RDBA是01 00 01 ad,……,第12个RDBA是01 00 03 45,注意这里记录的RDBA是以chunk为单位的起始RDBA,比如我这里的chunk size是32K(库的block size是8K),所以01 00 01 ad, 01 00 01 ae, 01 00 01 af, 01 00 01 b0都属于第一个chunk,即它们的page number都是0,但因为这四个block是连续的,且属于同一个chunk,所以oracle这里只需记录一个起始RDBA就可以了。
2、lob index的结构到底是怎样的?
答:lob index的结构类似于unique index的结构,它长度为50个byte,具体组成如下:
行头(1个byte)+ lock byte(1个byte)+ lob index key ( 32个byte,要么由16个byte的lob inode+4个RDBA组成,要么由8个RDBA组成) + lob id的长度(1个byte)+ lob id(10个byte)+ page number的长度(1个byte)+ page number(4个byte)
所以一共是1+1+32+1+10+1+4=50个byte
3、当lob index损坏后如何恢复?
答:DUL10号称是支持lob index损坏后的恢复的,但这里有一个最大的问题就是假如是disable storage in row,那么lob inode会存储在page number为0的lob index里,假如这个page number为0的lob index损坏了,那么我们就无法知道最后一个page里到底有多少byte是有效的。
col 0: [ 2] c1 02
col 1: [ 7] 63 75 69 68 75 61 31
col 2: [84]
00 54 00 01 01
00 00 36
02 85 01 00 03 0d 01 00 03 15 01 00 03 1d 01 00 03 25 01 00 03 2d 01 00 03
35 01 00 03 3d 01 00 03 45
比如上述例子里,我们知道最后一个lob page里有效的byte是1a d8
SQL> select to_number(‘1ad8′,’XXXXXXXX’) from dual;
TO_NUMBER(‘1AD8′,’XXXXXXXX’)
—————————-
6872
再来看相应的lob index:
row#0[7986] flag: ——, lock: 2, len=50, data:(32):
01 00 03 4d 01 00 03 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00
col 0; len 10; (10): 00 00 00 01 00 00 00 01 1e b9
col 1; len 4; (4): 00 00 00
这里可以看到,最后一个chunk的起始RDBA是01 00 03 55,但是朋友们千万不要以为这个就是那6872个byte所在的block,实际上,我dump后发现01 00 03 55里是个空的lob块(实际上这里也是一个full块,只不过所有的byte都是0x00,看起来就跟空块一样),真正的存储那6872个byte的block是01 00 03 57,而且我通过比对我insert的图片的最后几个byte和01 00 03 57中存储的内容,算出来刚好里面的有效的byte是6872:
SQL> select 286*24+8 from dual;
286*24+8
———-
6872
另外,这里也可以这么定位最后一个lob块:
在1da8(即6872)前面的那4个byte是0x00000036,表示这个LOB full block的块数,注意是块数,而不是chunk数。这里0x00000036=54个块,表示有54个块是满的,第55个不是满的,里面有6872字节。
再看下面那个lob index,page number从0x0c,即12开始,从0开始算的。那么这个chunk里面,之前已经有12*4=48个块是满的,这里01 00 03 4d开始的chunk,4个块也是满的,48+4=52,所以这个以01 00 03 55开头的chunk,有2个块是满的,就是01 00 03 55和 01 00 03 56,最后那个块我之前说的01 00 03 57了。
这就提示我们,当极端的情况下(disable storage in row且lob inode所在的lob index已经损坏),则我们需要扫描lob segment,取出其中存储的lob id和page number(相当于重构lob index),但是这里在扫描某个data object id所属的lob id和page number的时候,需要额外处理同一个lob id下的最大的page number——要去扫描这个page number下的所有block,且最大的RDBA里最后一个不为0的byte就是lob inode记录的最后一个page的有效byte数。
Recent Comments