解析数据文件(二)

接着解析数据文件(一)

BBED> p rowdata  <=======这个就是需要解析的数据了
ub1 rowdata[0]                              @8119     0x2c
ub1 rowdata[1]                              @8120     0x01
ub1 rowdata[2]                              @8121     0x03
ub1 rowdata[3]                              @8122     0x02
ub1 rowdata[4]                              @8123     0xc1
ub1 rowdata[5]                              @8124     0x04
ub1 rowdata[6]                              @8125     0x08
ub1 rowdata[7]                              @8126     0x68
ub1 rowdata[8]                              @8127     0x65
ub1 rowdata[9]                              @8128     0x68
ub1 rowdata[10]                             @8129     0x65
ub1 rowdata[11]                             @8130     0x68
ub1 rowdata[12]                             @8131     0x65
ub1 rowdata[13]                             @8132     0x68
ub1 rowdata[14]                             @8133     0x65
ub1 rowdata[15]                             @8134     0x07
ub1 rowdata[16]                             @8135     0x78
ub1 rowdata[17]                             @8136     0x77
ub1 rowdata[18]                             @8137     0x03
ub1 rowdata[19]                             @8138     0x12
ub1 rowdata[20]                             @8139     0x16
ub1 rowdata[21]                             @8140     0x37
ub1 rowdata[22]                             @8141     0x02
ub1 rowdata[23]                             @8142     0x2c
ub1 rowdata[24]                             @8143     0x01
ub1 rowdata[25]                             @8144     0x03
ub1 rowdata[26]                             @8145     0x02
ub1 rowdata[27]                             @8146     0xc1
ub1 rowdata[28]                             @8147     0x03
ub1 rowdata[29]                             @8148     0x08
ub1 rowdata[30]                             @8149     0x78
ub1 rowdata[31]                             @8150     0x69
ub1 rowdata[32]                             @8151     0x61
ub1 rowdata[33]                             @8152     0x6f
ub1 rowdata[34]                             @8153     0x68
ub1 rowdata[35]                             @8154     0x6f
ub1 rowdata[36]                             @8155     0x6e
ub1 rowdata[37]                             @8156     0x67
ub1 rowdata[38]                             @8157     0x07
ub1 rowdata[39]                             @8158     0x78
ub1 rowdata[40]                             @8159     0x77
ub1 rowdata[41]                             @8160     0x03
ub1 rowdata[42]                             @8161     0x12
ub1 rowdata[43]                             @8162     0x16
ub1 rowdata[44]                             @8163     0x36
ub1 rowdata[45]                             @8164     0x3a
ub1 rowdata[46]                             @8165     0x2c
ub1 rowdata[47]                             @8166     0x01
ub1 rowdata[48]                             @8167     0x03
ub1 rowdata[49]                             @8168     0x02
ub1 rowdata[50]                             @8169     0xc1
ub1 rowdata[51]                             @8170     0x02
ub1 rowdata[52]                             @8171     0x08
ub1 rowdata[53]                             @8172     0x78
ub1 rowdata[54]                             @8173     0x69
ub1 rowdata[55]                             @8174     0x61
ub1 rowdata[56]                             @8175     0x6f
ub1 rowdata[57]                             @8176     0x6d
ub1 rowdata[58]                             @8177     0x69
ub1 rowdata[59]                             @8178     0x6e
ub1 rowdata[60]                             @8179     0x67
ub1 rowdata[61]                             @8180     0x07
ub1 rowdata[62]                             @8181     0x78
ub1 rowdata[63]                             @8182     0x77
ub1 rowdata[64]                             @8183     0x03
ub1 rowdata[65]                             @8184     0x12
ub1 rowdata[66]                             @8185     0x16
ub1 rowdata[67]                             @8186     0x36
ub1 rowdata[68]                             @8187     0x36

这里的问题就是怎么能定位到rowdata数据的位置,并且rowdata的数据怎么转换成表的内容。
一个块的前20字节是块头信息,然后是一个固定的24位的事物信息 + 24*事物槽个数 + 14的表记录信息和空间使用信息 + kdbt*4(一个表占4个字节)+ kdbr*2(一个表占用2个字节)+freespace之后的位置就是数据真正的起始位置
所以真正的数据是从20+24+24*ktbbhict+14+kdbt*4+kdbr*2+8+freespace之后开始算起。
其中freespace = kdbhfseo - kdbhfsbo


block1表的第一行数据说明如下:
tl: 23 fb: --H-FL-- lb: 0x1  cc: 3         <========第三行数据
col  0: [ 2]  c1 04
col  1: [ 8]  68 65 68 65 68 65 68 65
col  2: [ 7]  78 77 03 12 16 37 02

数据的组成格式如下:

fb: --H-FL--标志   <====128 64 32 16 8 4 2 1 所以--H-FL-- = 32+8+4 = 44,转换成16进制为 2c,如果数据已经被删除,则为--HDFL- = 32+16+8+4 = 60转换成16进制为3c
lb: 0x1            <==== 事物槽标志   
cc: 3              <==== 该行数据有多少列
下面就是真正数据
col  0: [ 2]  c1 04
col  1: [ 8]  68 65 68 65 68 65 68 65
col  2: [ 7]  78 77 03 12 16 37 02

其中 col 0:[2] 2代表该列长度是2,其他同理。


然后查看rowdata的数据
ub1 rowdata[0]                              @8119     0x2c    <====对应fb --H-FL--标志  = 44 16进制是2c
ub1 rowdata[1]                              @8120     0x01    <====对应lb: 0x1
ub1 rowdata[2]                              @8121     0x03    <====cc: 3 有3列数据
ub1 rowdata[3]                              @8122     0x02    <====col 0: [2]  长度=2
ub1 rowdata[4]                              @8123     0xc1    
ub1 rowdata[5]                              @8124     0x04    
ub1 rowdata[6]                              @8125     0x08    <====col 1: [8]  长度=8
ub1 rowdata[7]                              @8126     0x68
ub1 rowdata[8]                              @8127     0x65
ub1 rowdata[9]                              @8128     0x68
ub1 rowdata[10]                             @8129     0x65
ub1 rowdata[11]                             @8130     0x68
ub1 rowdata[12]                             @8131     0x65
ub1 rowdata[13]                             @8132     0x68
ub1 rowdata[14]                             @8133     0x65
ub1 rowdata[15]                             @8134     0x07   <=====col 2: [7]  长度=7
ub1 rowdata[16]                             @8135     0x78
ub1 rowdata[17]                             @8136     0x77
ub1 rowdata[18]                             @8137     0x03
ub1 rowdata[19]                             @8138     0x12
ub1 rowdata[20]                             @8139     0x16
ub1 rowdata[21]                             @8140     0x37
ub1 rowdata[22]                             @8141     0x02


索引rowdata的数据格式为:
fb+lb+cc+(列数据) + fb+lb+cc+(列数据) 。。。。。,其中fb+lb+cc+(列数据)可以理解为一行数据。


实现的C代码(仅列出了重要的实现部分)如下:
scandata(uaddress,ulength)
{

        <===变量定义省略

         read( fd, buffer, 20 );
     memcpy(&kcbh,buffer,20);
     read(fd, buffer, 24);
     memcpy(&ktbbh,buffer,24);
     
     /*

            typedef struct ktbbh{
        ub4 ktbbhtyp;
        ub2 ktbbhsg1;
        ub2 ktbbhod1;
        ub4 kscnbas;
        ub4 kscnwrp;
        ub2 ktbbhict;
        ub1 ktbbhflg;
        ub1 ktbbhfsl;
        ub4 ktbbhfnx;
}KTBBH;
         
     */

     lseek( fd, BLOCK * k +20+24+ktbbh.ktbbhict*24, SEEK_SET );
     read(fd, buffer, 14 );
     memcpy(&kdbh, buffer, 14 );
          
          /*
        typedef struct kdbh {
        ub1     kdbhflag;
        ub1     kdbhntab;  <===获取表个数
        ub2     kdbhnrow;  <===行数
        ub2     kdbhfrre;
        ub2     kdbhfsbo;
        ub2     kdbhfseo;
        ub2     kdbhavsp;
        ub2     kdbhtosp;
                }KDBH;
          */

//ktbbh.ktbbhtyp=1代表是数据块, = 2代表是索引, checkaddress块的地址要再段头的一级块位图的范围
 if(nrow>0 && kcbh.type_kcbh==6 && ktbbh.ktbbhtyp==1 && checkaddress>=address && checkaddress<=(address+len-1))
 {
       lseek( fd, 0, SEEK_SET );
       lseek(fd,BLOCK*k+kdbh.kdbhntab*4+kdbh.kdbhnrow*2+kdbh.kdbhfseo-kdbh.kdbhfsbo+20+14+24+24*ktbbh.ktbbhict+8, SEEK_SET);
       printf("k=%d kdbhntab=%d  kdbhnrow=%d seo=%d sbo=%d\n", k, kdbh.kdbhntab, kdbh.kdbhnrow, kdbh.kdbhfseo,kdbh.kdbhfsbo);
       for ( i = 0; i < kdbh.kdbhnrow; i++ )   <====一共有多少行数据
       {
             read( fd, buffer, 3 );    //获取fb+lb+cc
              memcpy( &rowdata_header, buffer, 3 );
              /*
              typedef struct rowdata_header {
                    ub1     fb;
                    ub1     transaction;
                    ub1     column_count;
                            }ROWDATA_HEADER;
              */
              printf( "columns_count=%d\n", rowdata_header.column_count );

                       if(rowdata_header.column_count>0)    <====有多少列循环多少次
                       {
                               if(rowdata_header.flag!=60)  <=====60代表3c,代表数据已经被删除,删除的数据就不需要输出了
                               {
                                       for(cnt=0; cnt < rowdata_header.column_count; cnt++)
                                       {
                                               read( fd, buffer, 1 );     //cc下面的值,第一个代表该列有多长
                                               memcpy( &length, buffer, 1 );
                                               read( fd, data, length );
                                               for ( j = 0; j < length; j++ )  //把该列的值保存起来
                                               {
                                                      sprintf(temp+j*2,"%02x",*(data+j));
                                               }
                                                       printf("%s\n", temp);
                                       }
                               }
                                                }
                 }
     }
     
     
5、解析结果
这个时候解析表空间tablespace t 对应的数据文件'/u01/app/oradata/QXY/t.dbf'。
备注:c语言读取来的数据不一定是有序的

看程序的输出结果
[oracle@QXY1 jiexi]$ ./header | more       
objectid=134673                           <=====对象号134673 ,代表block1
address++++++++++++3400080 length=8       <=====address = 3400080就是L的地址,长度是8 
k=131 kdbhntab=1  kdbhnrow=3 kdbhfseo=8019 kdbhfsbo=24   <=====对应kdbh的数据, k=131 代表在哪个块。kdbhnrow该块有3行数据kdbhfseo-kdbhfsbo = freespace
columns_count=3
****col0****length= 2****value****=c104               <====真正的数据
****col1****length= 8****value****=6865686568656865
****col2****length= 7****value****=78770312163702
columns_count=3
****col0****length= 2****value****=c103
****col1****length= 8****value****=7869616f686f6e67
****col2****length= 7****value****=7877031216363a
columns_count=3
****col0****length= 2****value****=c102
****col1****length= 8****value****=7869616f6d696e67
****col2****length= 7****value****=78770312163636
objectid=134674                           <======对象号134674 代码block2
address++++++++++++3400088 length=8
k=139 kdbhntab=1  kdbhnrow=2 kdbhfseo=7944 kdbhfsbo=22   <=====block2的数据在139块
columns_count=2
****col0****length= 2****value****=c104
****col1****length= 58****value****=100540001020c80000002000000010000006f42d200440900000000000034000000000001006100620063006400650066006700680069006a006b006c
006d006e006f0070007100720073007400750076007700780079007a
columns_count=2
****col0****length= 2****value****=c103
****col1****length= 2a****value****=100540001020c80000002000000010000006f42d100160900000000000006000000000001006100620063
objectid=134677                           <=====134677对象号134677 代表block3
address++++++++++++34000a0 length=8
k=163 kdbhntab=1  kdbhnrow=242 kdbhfseo=1315 kdbhfsbo=502
columns_count=2
****col0****length= 3****value****=c23402
****col1****length= 14****value****=7971686b7a70716a6f746c686865686672787767
columns_count=2
****col0****length= 3****value****=c23403
****col1****length= 14****value****=1706165666a6c65727a746d7077696f7577796872
columns_count=2
****col0****length= 3****value****=c23404
****col1****length= 14****value****=16e707972796277736561786b73757868636d6279
columns_count=2
****col0****length= 3****value****=c23405
****col1****length= 14****value****=169637a6c63616265646f78666e75796e6361796e
columns_count=2
****col0****length= 3****value****=c23406
****col1****length= 14****value****=16d6362726e6a777a757174656267647070617662
columns_count=2
****col0****length= 3****value****=c23407
****col1****length= 14****value****=17174787276767976767675706f6471766d766c78
--More--


其实上面的这些数据就是oracle块中的表数据块了。

比如131块
buffer tsn: 15 rdba: 0x03400083 (13/131)
scn: 0x0000.01cf22fc seq: 0x01 flg: 0x06 tail: 0x22fc0601
frmt: 0x02 chkval: 0xee46 type: 0x06=trans data
Hex dump of block: st=0, typ_found=1


对应的数据
tab 0, row 0, @0x1f81
tl: 23 fb: --H-FL-- lb: 0x1  cc: 3
col  0: [ 2]  c1 02
col  1: [ 8]  78 69 61 6f 6d 69 6e 67
col  2: [ 7]  78 77 03 12 16 36 36
tab 0, row 1, @0x1f6a
tl: 23 fb: --H-FL-- lb: 0x1  cc: 3
col  0: [ 2]  c1 03
col  1: [ 8]  78 69 61 6f 68 6f 6e 67
col  2: [ 7]  78 77 03 12 16 36 3a
tab 0, row 2, @0x1f53
tl: 23 fb: --H-FL-- lb: 0x1  cc: 3
col  0: [ 2]  c1 04
col  1: [ 8]  68 65 68 65 68 65 68 65
col  2: [ 7]  78 77 03 12 16 37 02


139块的数据(其实就是block2的数据)
Block dump from disk:
buffer tsn: 15 rdba: 0x0340008b (13/139)
scn: 0x0000.01cf2342 seq: 0x01 flg: 0x06 tail: 0x23420601
frmt: 0x02 chkval: 0x179d type: 0x06=trans data
.
.
.
ntab=1
nrow=2
frre=-1
fsbo=0x16
fseo=0x1f08
avsp=0x1ef2
tosp=0x1ef2
0xe:pti[0]      nrow=2  offs=0
0x12:pri[0]     offs=0x1f67
0x14:pri[1]     offs=0x1f08
block_row_dump:
tab 0, row 0, @0x1f67
tl: 49 fb: --H-FL-- lb: 0x1  cc: 2
col  0: [ 2]  c1 03
col  1: [42]
 00 54 00 01 02 0c 80 00 00 02 00 00 00 01 00 00 00 6f 42 d1 00 16 09 00 00
 00 00 00 00 06 00 00 00 00 00 01 00 61 00 62 00 63
LOB
Locator:
  Length:        84(42)
  Version:        1
  Byte Length:    2
  LobID: 00.00.00.01.00.00.00.6f.42.d1
  Flags[ 0x02 0x0c 0x80 0x00 ]:
    Type: CLOB 
    Storage: BasicFile
    Enable Storage in Row 
    Characterset Format: IMPLICIT
    Partitioned Table: No
    Options: VaringWidthReadWrite 
  Inode: 
    Size:     22
    Flag:     0x09 [ Valid DataInRow ]
    Future:   0x00 (should be '0x00')
    Blocks:   0
    Bytes:    6
    Version:  00000.0000000001
    Inline data[6]
Dump of memory from 0x00007F70A900F9F6 to 0x00007F70A900F9FC
7F70A900F9F0          61000100 63006200               [...a.b.c]    
tab 0, row 1, @0x1f08
tl: 95 fb: --H-FL-- lb: 0x1  cc: 2
col  0: [ 2]  c1 04
col  1: [88]
 00 54 00 01 02 0c 80 00 00 02 00 00 00 01 00 00 00 6f 42 d2 00 44 09 00 00
 00 00 00 00 34 00 00 00 00 00 01 00 61 00 62 00 63 00 64 00 65 00 66 00 67
 00 68 00 69 00 6a 00 6b 00 6c 00 6d 00 6e 00 6f 00 70 00 71 00 72 00 73 00
 74 00 75 00 76 00 77 00 78 00 79 00 7a
LOB
Locator:
  Length:        84(88)
  Version:        1
  Byte Length:    2
  LobID: 00.00.00.01.00.00.00.6f.42.d2
  Flags[ 0x02 0x0c 0x80 0x00 ]:
    Type: CLOB 
    Storage: BasicFile
    Enable Storage in Row 
    Characterset Format: IMPLICIT
    Partitioned Table: No
    Options: VaringWidthReadWrite 
  Inode: 
    Size:     68
    Flag:     0x09 [ Valid DataInRow ]
    Future:   0x00 (should be '0x00')
    Blocks:   0
    Bytes:    52
    Version:  00000.0000000001
    Inline data[52]
Dump of memory from 0x00007F70A900F997 to 0x00007F70A900F9CB
7F70A900F990          00010000 00620061 00640063      [....a.b.c.d.]
7F70A900F9A0 00660065 00680067 006A0069 006C006B  [e.f.g.h.i.j.k.l.]
7F70A900F9B0 006E006D 0070006F 00720071 00740073  [m.n.o.p.q.r.s.t.]
7F70A900F9C0 00760075 00780077 2C7A0079           [u.v.w.x.y.z,]    
end_of_block_dump
End dump data blocks tsn: 15 file#: 13 minblk 139 maxblk 139

可以看到139块的数据和解析出来的是一样的
k=139 kdbhntab=1  kdbhnrow=2 kdbhfseo=7944 kdbhfsbo=22  
columns_count=2
****col0****length= 2****value****=c104
****col1****length= 58****value****=100540001020c80000002000000010000006f42d200440900000000000034000000000001006100620063006400650066006700680069006a006b006c
006d006e006f0070007100720073007400750076007700780079007a
columns_count=2
****col0****length= 2****value****=c103
****col1****length= 2a****value****=100540001020c80000002000000010000006f42d100160900000000000006000000000001006100620063

k=163 kdbhntab=1  kdbhnrow=242 kdbhfseo=1315 kdbhfsbo=502
163块的数据(block3有20000行数据,163块只有该表的242行数据)
验证如下:

Block dump from disk:
buffer tsn: 15 rdba: 0x034000a3 (13/163)
scn: 0x0000.01cf2b9f seq: 0x01 flg: 0x06 tail: 0x2b9f0601
frmt: 0x02 chkval: 0xc9e1 type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x00007FB0A2E69A00 to 0x00007FB0A2E6BA00
。。
。。
。。
data_block_dump,data header at 0x7fb0a2e69a64
===============
tsiz: 0x1f98
hsiz: 0x1f6
pbl: 0x7fb0a2e69a64
     76543210
flag=--------
ntab=1
nrow=242       <=====242行数据
frre=-1
fsbo=0x1f6
fseo=0x523
avsp=0x32d
tosp=0x32d
.
.
.
col  0: [ 3]  c2 34 02
col  1: [20]  79 71 68 6b 7a 70 71 6a 6f 74 6c 68 68 65 68 66 72 78 77 67
tab 0, row 16, @0x53f
tl: 28 fb: --H-FL-- lb: 0x1  cc: 2
col  0: [ 3]  c2 34 03
col  1: [20]  70 61 65 66 6a 6c 65 72 7a 74 6d 70 77 69 6f 75 77 79 68 72
tab 0, row 17, @0x55b
tl: 28 fb: --H-FL-- lb: 0x1  cc: 2
col  0: [ 3]  c2 34 04
col  1: [20]  6e 70 79 72 79 62 77 73 65 61 78 6b 73 75 78 68 63 6d 62 79
tab 0, row 18, @0x577
tl: 28 fb: --H-FL-- lb: 0x1  cc: 2
col  0: [ 3]  c2 34 05
col  1: [20]  69 63 7a 6c 63 61 62 65 64 6f 78 66 6e 75 79 6e 63 61 79 6e
tab 0, row 19, @0x593
tl: 28 fb: --H-FL-- lb: 0x1  cc: 2
col  0: [ 3]  c2 34 06
col  1: [20]  6d 63 62 72 6e 6a 77 7a 75 71 74 65 62 67 64 70 70 61 76 62
tab 0, row 20, @0x5af
tl: 28 fb: --H-FL-- lb: 0x1  cc: 2
col  0: [ 3]  c2 34 07
col  1: [20]  71 74 78 72 76 76 79 76 76 76 75 70 6f 64 71 76 6d 76 6c 78
.
.
.

对应解析的部分数据
k=163 kdbhntab=1  kdbhnrow=242 kdbhfseo=1315 kdbhfsbo=502
columns_count=2
****col0****length= 3****value****=c23402
****col1****length= 14****value****=7971686b7a70716a6f746c686865686672787767
columns_count=2
****col0****length= 3****value****=c23403
****col1****length= 14****value****=706165666a6c65727a746d7077696f7577796872
columns_count=2
****col0****length= 3****value****=c23404
****col1****length= 14****value****=6e707972796277736561786b73757868636d6279
columns_count=2
****col0****length= 3****value****=c23405
****col1****length= 14****value****=69637a6c63616265646f78666e75796e6361796e
columns_count=2
****col0****length= 3****value****=c23406
****col1****length= 14****value****=6d6362726e6a777a757174656267647070617662
columns_count=2
****col0****length= 3****value****=c23407
****col1****length= 14****value****=7174787276767976767675706f6471766d766c78
--More--


可以随机抽取一个验证,比如下面的一行数据
columns_count=2
****col0****length= 3****value****=c23407
****col1****length= 14****value****=7174787276767976767675706f6471766d766c78

SQL> 
SQL> select display_raw('c23407','NUMBER') from dual;

DISPLAY_RAW('C23407','NUMBER')
--------------------------------------------------------
5106

SQL> select display_raw('7174787276767976767675706f6471766d766c78','VARCHAR2') from dual;

DISPLAY_RAW('7174787276767976767675706F6471766D766C78','VARCHAR2')
---------------------------------------------------------------------------
qtxrvvyvvvupodqvmvlx

SQL> 

SQL> select * from block3 where age = 5106;  <=====数据都是正确的

       AGE NAME
---------- --------------------
      5106 qtxrvvyvvvupodqvmvlx

SQL> 

这些数据属于哪个表,表列的名字叫什么, 列是属于什么类型,需要解析system表空间的数据文件才能得到。到这里为止只是把表的数据解析出来,但是怎么把这些数据转换成能看懂的数据,这个就需要配合system数据文件,关于system数据文件的解析下次分享再介绍。

目前配合解析的system表空间得到最终效果如下:
[oracle@QXY1 proc]$ ./block  > block.txt 
[oracle@QXY1 proc]$ 
[oracle@QXY1 proc]$ cat block.txt 

当前对象号134673 name = bock1
                ID,NAME,CURDATE
                3                 hehehehe              2019-03-18 21:54:01
                2                 xiaohong              2019-03-18 21:53:57
                1                 xiaoming              2019-03-18 21:53:53


当前对象号134674 name = bock2                   
                ID,NAME                                                                                            
                3               abcdefghijklmnopqrstuvwxyz
                2                      abc 
                
           
当前对象号134677 name = bock3            
                AGE,NAME                                                                                           
                5101            yqhkzpqjotlhhehfrxwg
                5102            paefjlerztmpwiouwyhr
                5103            npyrybwseaxksuxhcmby
                5104            iczlcabedoxfnuyncayn
                5105            mcbrnjwzuqtebgdppavb
                5106            qtxrvvyvvvupodqvmvlx
                5107            qvieuavcuupsuvehyami
                5108            fqojtjzocomgvegkustq
                5109            qnnpryxmdddrmagkeisw
                5110            pijpyvdpoyyonaywplww
                5111            ndfoptrznyhjbdgojreg
                5112            wvbrebnbmchsmylebapl
                5113            ulypbedxrdcmhxnrftqb
                5114            wyszxtocdwadcdvyaeow
                5115            eqntavjrrcgxyilrensf
                5116            bebugykhbcnkjeuwtcqo
                5117            vuacelvgrodbipqloyab
                5118            xxbbgbuskcgzisifqxay
                .
                .
                .
                .

下次分享会介绍数据是怎么转换成可读的,并且数据属于哪个表,表列叫什么等等。。

猜你喜欢

转载自blog.csdn.net/m15217321304/article/details/88711015