mysql row模式行记录分析

接着上一篇,继续研究

废话不多说,直接gdb进入unpack_row

Breakpoint 7, unpack_row (rli=0x1e9f6a00, table=0x1ea2b430, colcnt=5, row_data=0x1e9e80f0 "�\001", cols=0x1e9ee610, row_end=0x1e9ee6a8, master_reclength=0x1e9ee658, abort_on_warning=false, first_row=true) at rpl_record.cc:184 184 const bool abort_on_warning, const bool first_row)

插入的数据是:

insert into xx values(1,2,"sdf",13,"sss");


可以看到,row_data行数据中是乱码,对下面的代码进行分析后可以得出:

1.首先进行偏移:

size_t const master_null_byte_count= (bitmap_bits_set(cols) + 7) / 8;

其中bitmap_bits_set(cols) 为列的个数


uchar const *pack_ptr= row_data + master_null_byte_count

(gdb) p pack_ptr
$149 = (const uchar *) 0x1e9e80f1 "\001"


打印:

(gdb) p pack_ptr[0]
$150 = 1 '\001'
(gdb) p pack_ptr[1]
$151 = 0 '\0'

其中1为插入的第一列数据,以'\0'结束,为了验证我们的想法,继续打印:

(gdb) p pack_ptr[2]
$152 = 0 '\0'
(gdb) p pack_ptr[3]
$153 = 0 '\0'
(gdb) p pack_ptr[4]
$154 = 2 '\002'
(gdb) p pack_ptr[5]
$155 = 0 '\0'

可见当向后偏移到第一个非‘\0’位置时,表示的是第二列的数据‘2’

那么对字符串,这里是如何处理的呢?

(gdb) p pack_ptr[8]
$158 = 3 '\003'
(gdb) p pack_ptr[9]
$159 = 115 's'
(gdb) p pack_ptr[9]@3
$160 = "sdf"

挨着上次的跳过\0,我们可以看到对于字符串,首先有一个数字来表示字符串的长度,然后紧跟着相应的字符串

接着看下一个数字13:

(gdb) p row_data[13]
$219 = 13 '\r'

这个数字紧挨着上一个字符串之后,这表明列数据无需用''\0'间隔

三个字节的'\0'后,下一个字符串:

(gdb) p row_data[17]
$223 = 3 '\003'
(gdb) p row_data[18]
$224 = 115 's'
(gdb) p row_data[19]
$225 = 115 's'
(gdb) p row_data[20]
$226 = 115 's'
(gdb) p row_data[21]
$227 = 0 '\0'

同样的,row_data[17]表示其后字符串的长度,然后跟着'sss'


基于上述分析,我们可以推测:

1.'\0'是用来填充字节的

2.列数据与列数据之间除了'\0'没有其他填充

3.对于字符串,会记录其数据的字节数


那么对于值为NULL的情况该如何处理呢?

插入数据:insert into xx values(1,2,"sdf",NULL,"sss");

(gdb) p row_data[1]
$232 = 1 '\001'
(gdb) p row_data[2]
$233 = 0 '\0'
(gdb) p row_data[3]
$234 = 0 '\0'
(gdb) p row_data[4]
$235 = 0 '\0'
(gdb) p row_data[5]
$236 = 2 '\002'
(gdb) p row_data[6]
$237 = 0 '\0'
(gdb) p row_data[8]
$238 = 0 '\0'
(gdb) p row_data[9]
$239 = 3 '\003'
(gdb) p row_data[10]
$240 = 115 's'
(gdb) p row_data[11]
$241 = 100 'd'
(gdb) p row_data[12]
$242 = 102 'f'
(gdb) p row_data[13]
$243 = 3 '\003'
(gdb) p row_data[14]
$244 = 115 's'
(gdb) p row_data[15]
$245 = 115 's'
(gdb) p row_data[16]
$246 = 115 's'

我们可以看到,值为NULL时,在行数据中是不存在的,那么何时才知道我们该忽略某个值为NULL的列呢??

简单的实验了一下,null值似乎记录在row_data的第一个字节内:

例如:

当输入为:insert into xx values(1,NULL,NULL,NULL,"ssss");

row_data[0] = 238

二进制:1110 1110

当输入为:insert into xx values(1,NULL,NULL,15,"ssss");

row_data[0]=230

二进制:1110 0110

猜测如下:

第一个字节的低5位代表5个列。高位为最后一个列,低位为第一个列。

当值为1时,表示该值为NULL,在解析行数据时,可以忽略,

当值为0时,则表示该列数据不为空,可以从行数据中解析得到。


下一步:证实上述猜想!!!!









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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值