翻出了 oracle 一些老东西 放这里了 oracle 数据结构解析

Clob 类型字段的内部存储初步探索

                      Lsliang   pconline.com.cn


 

前言: 本篇文章仅供参考,此为一家之言,仅代表个人观点,欢迎有有此爱好的同行门拍砖, 其中部分结构还没有搞清除。

 我google / baidu 了n多次,目前尚未在web上发现关于此类的文章。

本人有幸从WEB上得到了一些关于oracle 数据类型内部存储的介绍类的文章,于是尝试解析lob类型字段。废话来来。开始干活。:)

1。Dsi 中介绍的LOB类型的内部结构。

 There are three structures for internal LOBs:

– LOB Locator: kolbl (20 bytes)

– LOB Inode: kdlinode (16 bytes minimum)

– Data array

The physical location of these three components

could be up to three different segments:

len(2), vsn(2), flg(4), bytl(2), lobid(10), inode(16),

data

len = maximum length of the LOB locator excluding these two len bytes

vsn = version of the LOB locator structure

flg = 4 flag bytes

bytl = byte length (1 for BLOB/CLOB/BFILE. Value for NCLOB)

lobid = 2 bytes for index followed by 8 byte LOB OID. Key into LOB index

inode = kdlinode structure

data = actual LOB data

Internal LOB locator without inode:

len(2), vsn(2), flg(4), bytl(2), lobid(10)

Len = maximum length of the LOB locator excluding these two len bytes

vsn = version of the LOB locator structure

flg = 4 flag bytes

bytl = byte length (1 for BLOB/CLOB/BFILE. Value for NCLOB)

lobid = 2 bytes for index followed by 8 byte LOB OID. Key into LOB index

SQL*Plus: Release 10.2.0.3.0 - Production on ?????? 5?? 27 04:46:43 2008

Copyright (c) 1982, 2006, Oracle.  All Rights Reserved.

Connected to:

Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit Production

With the Partitioning, OLAP and Data Mining options

SQL> drop user lsliang cascade ;

User dropped.

SQL> drop tablespace test ;

Tablespace dropped.

SQL> create tablespace   test datafile '/oracle/oradata/sunha5/test01.dbf' size 1m reuse; 

Tablespace created.

SQL> create user lsliang  identified by lsliang ;

User created.

SQL> grant dba to lsliang ;

Grant succeeded.

SQL> conn  lsliang/lsliang ;

Connected.

SQL> create table  test (id number ,name varchar2(10), text clob) tablespace test ;

Table created.

SQL> insert into test values( 1,'lsl','aaaaa') ;

1 row created.

SQL> commit; 

Commit complete.

SQL> alter system checkpoint; 

System altered.

SQL> 

SQL> select rowid from  test ;

ROWID

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

AAAPIoAAVAAAAAQAAA

SQL> 

[oracle@sunha2 baby]$ perl rowid.pl AAAPIoAAVAAAAAQAAA

        For  this  Rowid : AAAPIoAAVAAAAAQAAA

        The  dba_objets -- data_object_id = 61992 

        The  data_file -- datafile# = 21 

        The  data_block -- data_block# = 16 

        This  Record  in the  datablock is 0 

## rowid.pl 是一个解析rowid 的perl脚本,具体rowid 如何解析请参考网络上的文章。

  [oracle@sunha5 sunha5]$ ./a.out test01.dbf  16

        file#: 21

        block#: 16

        type: 0X6

        fmt:0Xa2 --0X02

        rdba: 0X5400010

        bas SCN:0Xf4a9a73

        wrap SCN: 0X0000

        flag: 0X6

        chk: 0Xb6e0

数据块的块头的信息。  A.out 为解析数据文件块头的c程序,具体请参考网络上数据块的结构。 

Vi a1  

*** 2008-05-27 05:44:53.154

*** ACTION NAME:() 2008-05-27 05:44:53.153

*** MODULE NAME:(SQL*Plus) 2008-05-27 05:44:53.153

*** SERVICE NAME:(SYS$USERS) 2008-05-27 05:44:53.153

*** SESSION ID:(1652.49666) 2008-05-27 05:44:53.153

Start dump data blocks tsn: 22 file#: 21 minblk 16 maxblk 16

buffer tsn: 22 rdba: 0x05400010 (21/16)

scn: 0x0000.0f4a9a73 seq: 0x03 flg: 0x06 tail: 0x9a730603

frmt: 0x02 chkval: 0xb6e0 type: 0x06=trans data

Hex dump of block: st=0, typ_found=1

Hex dump of block: st=0, typ_found=1

Dump of memory from 0x0000000106768C00 to 0x000000010676AC00

106768C00 06A20000 05400010 0F4A9A73 00000306  [.....@...J.s....]

106768C10 B6E00000 01270019 0000F228 0F4A99DE  [.....'.....(.J..]

106768C20 00000000 1F023200 05400009 00370026  [......2..@...7.&]

106768C30 00000619 00800384 01052D00 20010000  [..........-. ...]

......................

......................

10676AB90 010078D0 2C000FFF 00000000 FFFFFFFF  [..x.,...........]

10676ABA0 7FFEEEB8 00000004 1E629308 003E002C  [.........b...>.,]

10676ABB0 00008000 00000027 C20F3F4B C5162F24  [.......'..?K../$]

10676ABC0 154A062C 010302C1 02036C73 6C2E0054  [.J.,......lsl..T]

10676ABD0 0001020C 80000002 00000001 00000038  [...............8]

10676ABE0 EF33001A 09000000 0000000A 00000000  [.3..............]

10676ABF0 00010061 00610061 00610061 9A730603  [...a.a.a.a.a.s..]

Block header dump:  0x05400010

Object id on Block? Y

 seg/obj: 0xf228  csc: 0x00.f4a99de  itc: 2  flg: E  typ: 1 - DATA

     brn: 0  bdba: 0x5400009 ver: 0x01 opc: 0

     inc: 0  exflg: 0

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0x01   0x0037.026.00000619  0x00800384.0105.2d  --U-    1  fsc 0x0000.0f4a9a73

0x02   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000

data_block_dump,data header at 0x106768c64

===============

tsiz: 0x1f98

hsiz: 0x14

pbl: 0x106768c64

bdba: 0x05400010

     76543210

flag=--------

ntab=1

nrow=1

frre=-1

fsbo=0x14

fseo=0x1f5f

avsp=0x1f4b

tosp=0x1f4b

0xe:pti[0]      nrow=1  offs=0

0x12:pri[0]     offs=0x1f5f

block_row_dump:

tab 0, row 0, @0x1f5f

tl: 57 fb: --H-FL-- lb: 0x1  cc: 3

col  0: [ 2]  c1 02

col  1: [ 3]  6c 73 6c

col  2: [46]

 00 54 00 01 02 0c 80 00 00 02 00 00 00 01 00 00 00 38 ef 33 00 1a 09 00 00

 00 00 00 00 0a 00 00 00 00 00 01 00 61 00 61 00 61 00 61 00 61

end_of_block_dump

End dump data blocks tsn: 22 file#: 21 minblk 16 maxblk 16

解说: 

对于数据长度小于4000的情况,lob列的数据存放在行内,如上图,数据的存储格式是ascii码存放。

Lob数据的结构,头部最大为84字节,最小为36字节

对于本例:

                   2E0054  [.J.,......lsl..T]

10676ABD0 0001020C 80000002 00000001 00000038  [...............8]

10676ABE0 EF33001A 09000000 0000000A 00000000  [.3..............]

10676ABF0 00010061 00610061 00610061 9A730603  [...a.a.a.a.a.s..]

2E : 列的长度46 -- col  2: [46]

0054  lob head 的最大长度,

0001 vsn 

02 0c 80 00 flag  

00 02    数据的单位长度为2个字节。

00 00 00 01 00 00 00 38 ef 33  lob_id 

00 1a 09 00 00 00 00 00 00 0a 00 00 00 00 00 01  inodeid 

00 61 00 61 00 61 00 61 00 61  data数据: 我们插入的那5个a .

 经过我的测试 对inodeid  最后一位是一个开关变量(01,02) 

01 表示数据在行内存放,

02 表示数据存储在log段中。

SQL> @a.sql;

PL/SQL procedure successfully completed.

SQL> alter system  checkpoint ;

System altered.

SQL> commit;

Commit complete.

More  a.sql ; 

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

declare

a clob;

b varchar2(32000) ;

begin

b:=lpad('a',4000,'a') ;

a:=a||b ;

--a:=a||a;

--a:=a||a;

--a:=a||a;

--a:=a||a;

--a:=a||a;

--a:=a||a;

 update lsliang.test set text=a ;

commit ;

end ;

/

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

##  a.sql  用来更新lob字段。

Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit Production

With the Partitioning, OLAP and Data Mining options

SQL> alter system dump datafile 21 block 16 ;

System altered.

SQL> 

Block header dump:  0x05400010

 Object id on Block? Y

 seg/obj: 0xf228  csc: 0x00.f4b132c  itc: 2  flg: E  typ: 1 - DATA

     brn: 0  bdba: 0x5400009 ver: 0x01 opc: 0

     inc: 0  exflg: 0

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0x01   0x0037.026.00000619  0x00800384.0105.2d  C---    0  scn 0x0000.0f4a9a73

0x02   0x0017.026.00000ae0  0x00801869.01b9.3c  --U-    1  fsc 0x0006.0f4b132d

data_block_dump,data header at 0x106768c64

===============

tsiz: 0x1f98

hsiz: 0x14

pbl: 0x106768c64

bdba: 0x05400010

     76543210

flag=--------

ntab=1

nrow=1

frre=-1

fsbo=0x14

fseo=0x1f2c

avsp=0x1f4b

tosp=0x1f51

0xe:pti[0]      nrow=1  offs=0

0x12:pri[0]     offs=0x1f2c

block_row_dump:

tab 0, row 0, @0x1f2c

tl: 51 fb: --H-FL-- lb: 0x2  cc: 3

col  0: [ 2]  c1 02

col  1: [ 3]  6c 73 6c

col  2: [40]

 00 54 00 01 02 0c 80 00 00 02 00 00 00 01 00 00 00 38 ef 34 00 14 05 00 00

 00 00 00 1f 40 00 00 00 00 00 02 05 40 00 18

end_of_block_dump

End dump data blocks tsn: 22 file#: 21 minblk 16 maxblk 16

0054  lob head 的最大长度,

0001 vsn 

02 0c 80 00 flag  

00 02    数据的单位长度为2个字节。

00 00 00 01 00 00 00 38 ef 34  lob_id 

00 14 05 00 00 00 00 00 1f 40 00 00 00 00 00 02  inodeid 

 05 40 00 18         data部分没有了,取而代之的是rdba 

我们来看看 ox05400018放的是什么东西。

SQL*Plus: Release 10.2.0.3.0 - Production on ?????? 5?? 27 07:00:18 2008

Copyright (c) 1982, 2006, Oracle.  All Rights Reserved.

Connected to:

Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit Production

With the Partitioning, OLAP and Data Mining options

SQL> alter system dump datafile 21 block 24 ;

System altered.

SQL> 

[oracle@sunha5 sunha5]$ ./a.out test01.dbf  24

        file#: 21

        block#: 24

        type: 0X28

        fmt:0Xa2 --0X02

        rdba: 0X5400018

        bas SCN:0Xf4b132c

        wrap SCN: 0X0000

        flag: 0X4

        chk: 0X10c3

*** 2008-05-27 07:00:32.904

*** SERVICE NAME:(SYS$USERS) 2008-05-27 07:00:32.904

*** SESSION ID:(510.3928) 2008-05-27 07:00:32.904

Start dump data blocks tsn: 22 file#: 21 minblk 24 maxblk 24

buffer tsn: 22 rdba: 0x05400018 (21/24)

scn: 0x0000.0f4b132c seq: 0x02 flg: 0x04 tail: 0x132c2802

frmt: 0x02 chkval: 0x10c3 type: 0x28=PAGETABLE MANAGED LOB BLOCK

Hex dump of block: st=0, typ_found=1

Dump of memory from 0x0000000106768C00 to 0x000000010676AC00

106768C00 28A20000 05400018 0F4B132C 00000204  [(....@...K.,....]

106768C10 10C30000 0000F229 00000001 00000038  [.......).......8]

106768C20 EF340000 00000001 00000000 00000000  [.4..............]

106768C30 05400011 00000000 00610061 00610061  [.@.......a.a.a.a]

106768C40 00610061 00610061 00610061 00610061  [.a.a.a.a.a.a.a.a]

        Repeat 498 times

10676AB70 00610061 00610061 00200020 00200020  [.a.a.a.a. . . . ]

10676AB80 00200020 00200020 00200020 00200020  [. . . . . . . . ]

        Repeat 6 times

10676ABF0 00200020 00200020 00200020 132C2802  [. . . . . . .,(.]

Long field block dump:

Object Id    61993

LobId: 000100038EF34 PageNo        0

Version: 0x0000.00000001  pdba: 88080401

00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61

    00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61

00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61

。。。。。。。。。。。。。。。。。

。。。。。。。。。。。。。。。。

 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61

 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61

 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61

 00 61 00 61 00 61 00 61 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20

 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20

 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20

 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20

 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20

 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20

End dump data blocks tsn: 22 file#: 21 minblk 24 maxblk 24

可以看出来了,0x05400018 是一个lob段,保存了我们刚才update的数据

(@a.sql   update  lsliang.test set text=a;  a=40000 * a ) 

从这里可以看出 :

106768C30 05400011 00000000 00610061 00610061  [.@.......a.a.a.a]

106768C40 00610061 00610061 00610061 00610061  [.a.a.a.a.a.a.a.a]

        Repeat 498 times

10676AB70 00610061 00610061 00200020 00200020  [.a.a.a.a. . . . ]

刚好是498*8个a + 8个a + 2*4个a =4000个a  。 

再回过头来看看ox05400010 

col  2: [40]

 00 54 00 01 02 0c 80 00 00 02 00 00 00 01 00 00 00 38 ef 34 00 14 05 00 00

 00 00 00 1f 40 00 00 00 00 00 02 05 40 00 18

0054  lob head 的最大长度,

0001 vsn 

02 0c 80 00 flag  

00 02    数据的单位长度为2个字节。

00 00 00 01 00 00 00 38 ef 34  lob_id 

00 14 05 00 00 00 00 00 1f 40 00 00 00 00 00 02  inodeid 

05 40 00 18         data部分没有了,取而代之的是rdba 

看到了吧 inodeid的最后一位是02 即数据存储行外的log段,其后面放置的就是

Log列数据存储的log段的rdba.

还有一个 00 14 05 00 00 00 00 00 1f 40 00 00 00 00 00 02 的红色部分“00 00 00 00 00 1f 40”表示的就是我们存储的数据的长度的16进制的表示。

[oracle@test231 ~]$ hex2i  0x1f40  

 argv[] = 8000  -- 8 -- 17500  -- 16 0x1f40

[oracle@test231 ~]$  ##  hex2i 为10,8 ,16进制之间转换的小脚本请自行实现。

我们实际存储的是4000个a ,lobhead里定义的bytl=0x02 两个字节。总共8000字节。

[oracle@test231 ~]$  ##  hex2i 为10,8 ,16进制之间转换的小脚本请自行实现。

00 14 05 00 00 00 00 00 1f 40 00 00 00 00 00 02  inodeid 中的”00 14 05“这部分是作什么的呢? 我本人目前还没有解决,欢迎大家发表意见。

再来看 0x05400018 这个lob段,

106768C00 28A20000 05400018 0F4B132C 00000204  [(....@...K.,....]

106768C10 10C30000 0000F229 00000001 00000038  [.......).......8]

106768C20 EF340000 00000001 00000000 00000000  [.4..............]

106768C30 05400011 00000000 00610061 00610061  [.@.......a.a.a.a]

106768C40 00610061 00610061 00610061 00610061  [.a.a.a.a.a.a.a.a]

28A20000 05400018 0F4B132C 00000204

10C30000“ 这是block head 部分

下面的部分中

                   0000F229 00000001 00000038  [.......).......8]

106768C20 EF340000 00000001 00000000 00000000  [.4..............]

106768C30 05400011 00000000

" 0000F229" 这部分代表的是objectid oxf229=61993;

QL> select * from  dba_objects where object_id=61993;

OWNER    OBJECT_NAME                    OBJECT_ID   DATA_OBJECT_ID

LSLIANG  SYS_LOB0000061992C00003$$           61993          61993 LOB

"00000001 00000038EF34" 红色部分是lobid

"0000 00000001 " 蓝色部分Version: 0x0000.00000001

"00000000 00000000" 绿色部分是page no 当一个lob列分为多个chunc的时候,page no 确定该block的数据在整个lob列中的位置。

" 05400011 " 黄色部分 为PDBA 即lob段的block的空闲列表(freelist bitmap ) 

我们对这部分的展开将在以后给出。

"00000000"  最后的这几个0代表什么呢?? 

现在时间 :

[oracle@sunha5 udump]$ date 

Tue May 27 08:05:33 CST 2008 

又一个不眠之夜。 后续的部分我会继续推出。 


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/133735/viewspace-1788221/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/133735/viewspace-1788221/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值