MySQL协议分析

栏目: 数据库 · 发布时间: 5年前

内容简介:MySQL协议分析,主要参考MySQL Forge上的在做proxy的时候在这里迷糊过,翻了几遍代码才搞明白,细节如下:客户端服务端的net->pkt_nr都从0开始.接受包时比较packet number 和net->pkt_nr是否相等,否则报packet number乱序,连接报错;相等则pkt_nr自增.发送包时把net->pkt_nr作为packet number发送,然后对net->pkt_nr进行自增保持和对端的同步.

MySQL协议分析,主要参考MySQL Forge上的 wiki 和源码.协议的全图见 这里 , 给同事分享的ppt见 这里 ,下载见 这里

packet number

在做proxy的时候在这里迷糊过,翻了几遍代码才搞明白,细节如下:

客户端服务端的net->pkt_nr都从0开始.接受包时比较packet number 和net->pkt_nr是否相等,否则报packet number乱序,连接报错;相等则pkt_nr自增.发送包时把net->pkt_nr作为packet number发送,然后对net->pkt_nr进行自增保持和对端的同步.

接收包

sql/net_serv.c:my_real_read

898     if (net->buff[net->where_b + 3] != (uchar) net->pkt_nr)

发送包

sql/net_serv.c:my_net_write

392   int3store(buff,len);
393   buff[3]= (uchar) net->pkt_nr++;

我们来几个具体场景的packet number, net->pkt_nr的变化

连接

0 c ———-> s 0  connect

0 c <—-0——s 1  handshake

2 c —-1—->s 1 auth

2c <—-2——s 0 ok

开始两方都为0,服务端发送handshake packet(pkt=0)之后自增为1,然后等待对端发送过来pkt=1的包

查询

每次查询,服务客户端都会对net->pkt_nr进行清零

include/mysql_com.h
388 #define net_new_transaction(net) ((net)->pkt_nr=0)
sql/sql_parse.cc:do_command
805   net_new_transaction(net);

sql/client.c:cli_advanced_command

800   net_clear(&mysql->net, (command != COM_QUIT));

开始两方net->pkt_nr皆为0, 命令发送后客户端端为1,服务端开始发送分包,分包的pkt_nr的依次递增,客户端的net->pkt_nr也随之增加.

1 c ——0—-> s 0  query

1 c <—-1——s 2  resultset

2 c <—-2——s 3  resultset

解包的细节

my_net_read负责解包,首先读取4个字节,判断packet number是否等于net->pkt_nr然后再次读取packet_number长度的包体。

伪代码如下:

remain=4
for(i = 0; i < 2; i++) {
    //数据是否读完
    while (remain>0)  {
        length = read(fd, net->buff, remain)
        remain = remain - length
    }
    //第一次
    if (i=0) {
        remain = uint3korr(net->buff+net->where_b);
    }
}

网络层优化

从ppt里可以看到,一个resultset packet由多个包组成,如果每次读写包都导致系统调用那肯定是不合理,常规优化方法:写大包加预读

net->buff

每个包发送到网络或者从网络读包都会先把数据包保存在net->buff里,待到net->buff满了或者一次命令结束才会通过socket发出给对端.net->buff有个初始大小(net->max_packet),会随读取数据的增多而扩展.

vio->read_buffer

每次从网络读包,并不是按包的大小读取,而是会尽量读取2048个字节,这样一个resultset包的读取不会再引起多次的系统调用了.header packet读取完毕后, 接下来的field,eof, row apcket读取仅仅需要从vio-read_buffer拷贝指定字节的数据即可.

MySQL api说明

api和 MySQL 客户端都会使用sql/client.c这个文件,解包的过程都是使用sql/client.c:cli_read_query_result.

mysql_store_result来解析row packet,并把数据存储到res->data里,此时所有数据都存内存里了.

mysql_fetch_row仅仅是使用内部的游标,遍历result->data里的数据

3052     if (!res->data_cursor)
3053     {
3054       DBUG_PRINT("info",("end of data"));
3055       DBUG_RETURN(res->current_row=(MYSQL_ROW) NULL);
3056     }
3057     tmp = res->data_cursor->data;
3058     res->data_cursor = res->data_cursor->next;
3059     DBUG_RETURN(res->current_row=tmp);

mysql_free_result是把result->data指定的行数据释放掉.


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

超简单!一学就懂的互联网金融

超简单!一学就懂的互联网金融

视觉图文 / 人民邮电出版社 / 2015-2-1 / 45.00元

零基础、全图解,通过130多个精辟的知识点、220多张通俗易懂的逻辑图表,让您一书在手,即可彻底看懂、玩转互联网金融从菜鸟成为达人,从新手成为互联网金融高手! 本书主要特色:最简洁的版式+最直观的图解+最实用的内容。 本书细节特色:10章专题内容详解+80多个特别提醒奉献+130多个知识点讲解+220多张图片全程图解,深度剖析互联网金融的精华之处,帮助读者在最短的时间内掌握互联网金融知......一起来看看 《超简单!一学就懂的互联网金融》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具