Some lob internal

这篇文章源于我昨天和今天跟老熊的无数次电话交流,老熊是极其强悍的,每次我跟他讨论完问题后,我对某个知识点的认识都能得到质的提高,再次感谢老熊!

 

1402e里这么提到——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就是指的12chunk的起始RDBA

col  0: [ 2]  c1 02

col  1: [ 7]  63 75 69 68 75 61 31

col  2: [84]

 00 54 00 01 01 0c 00 00 00 01 00 00 00 01 00 00 00 01 1e b9 00 40 05 00 00

 00 00 36 1a d8 00 00 00 00 00 02 01 00 01 ad 01 00 02 75 01 00 02 7d 01 00

 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 id00 00 00 01 00 00 00 01 1e b9,这里的第36byte到第84byte就是12RDBA,第1RDBA01 00 01 ad,……,第12RDBA01 00 03 45,注意这里记录的RDBA是以chunk为单位的起始RDBA,比如我这里的chunk size32K(库的block size8K),所以01 00 01 ad, 01 00 01 ae, 01 00 01 af, 01 00 01 b0都属于第一个chunk,即它们的page number都是0,但因为这四个block是连续的,且属于同一个chunk,所以oracle这里只需记录一个起始RDBA就可以了。

 

2lob index的结构到底是怎样的?

答:lob index的结构类似于unique index的结构,它长度为50byte,具体组成如下:

行头(1byte)+ lock byte1byte)+ lob index key ( 32byte,要么由16bytelob inode+4RDBA组成,要么由8RDBA组成) lob id的长度(1byte)+ lob id10byte)+ page number的长度(1byte)+ page number4byte

所以一共是1+1+32+1+10+1+4=50byte

 

3lob index损坏后如何恢复?

答:DUL10号称是支持lob index损坏后的恢复的,但这里有一个最大的问题就是假如是disable storage in row,那么lob inode会存储在page number0lob index里,假如这个page number0lob 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 0c 00 00 00 01 00 00 00 01 00 00 00 01 1e b9 00 40 05 00 00

 00 00 36 1a d8 00 00 00 00 00 02 01 00 01 ad 01 00 02 75 01 00 02 7d 01 00

 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里有效的byte1a 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 0c

 

这里可以看到,最后一个chunk的起始RDBA01 00 03 55但是朋友们千万不要以为这个就是那6872byte所在的block,实际上,我dump后发现01 00 03 55里是个空的lob块(实际上这里也是一个full块,只不过所有的byte都是0x00,看起来就跟空块一样),真正的存储那6872byteblock01 00 03 57,而且我通过比对我insert的图片的最后几个byte01 00 03 57中存储的内容,算出来刚好里面的有效的byte6872

SQL> select 286*24+8 from dual;

 

  286*24+8

———-

      6872

 

另外,这里也可以这么定位最后一个lob块:

1da8(即6872)前面的那4byte0x00000036,表示这个LOB  full block的块数,注意是块数,而不是chunk数。这里0x00000036=54个块,表示有54个块是满的,第55个不是满的,里面有6872字节。

 

再看下面那个lob indexpage number0x0c,即12开始,从0开始算的。那么这个chunk里面,之前已经有12*4=48个块是满的,这里01 00 03 4d开始的chunk4个块也是满的,48+4=52,所以这个以01 00 03 55开头的chunk,有2个块是满的,就是01 00 03 55 01 00 03 56,最后那个块我之前说的01 00 03 57了。

 

这就提示我们,当极端的情况下(disable storage in rowlob inode所在的lob index已经损坏),则我们需要扫描lob segment,取出其中存储的lob idpage number(相当于重构lob index),但是这里在扫描某个data object id所属的lob idpage number的时候,需要额外处理同一个lob id下的最大的page number——要去扫描这个page number下的所有block,且最大的RDBA里最后一个不为0byte就是lob inode记录的最后一个page的有效byte数。