MySQL协议分析

本来看MySQL协议是要做一个skynet的lua c库的,今天群里有人实现了,主要是根据openresty/lua-resty-mysql改的,之前工作老停留在协议内容上,不过也好,充分学些了一些MySQL协议。

同时这个项目也值得关注OpenResty

一次正常的过程如下

  1.  三次握手建立tcp连接
  2. 建立MySql连接 
    a) 服务端往客户端发送握手初始化包(Handshake Initialization Packet)
    b) 客户端往服务端发送验证包(Client Authentication Packet)
    c) 服务端往客户端发送成功包
  3. 客户端与服务端之间交互
    a) 客户端往服务端发送命令包(Command Packet) 
    b) 服务端往客户端发送回应包(OK Packet, or Error Packet, or Result Set Packet) 
  4. 断开MySql连接 
    a) 客户端往服务端发送退出命令包 
  5. 四次握手断开tcp连接 

Packet

在mysql中,如果client或server要发送数据,它需要将数据按照(2 ** 24 - 1)拆分成packet,给每一个packet添加header,然后再以此发送。
对于一个packet,格式如下:

3              payload length
1              sequence id
string[len]    payload

前面3个字节表明的是该packet的长度,每个packet最大不超过16MB。第4个字节表明的是该packet的序列号,从0开始,对于多个packet依次递增,等到下一个新的命令发送数据的时候才重置为0。前面4个字节组成了一个packet的header,后面就是该packet实际的数据。

因为一个packet最大能发送的数据位16MB,所以如果需要发送大于16MB的数据,就需要拆分成多个packet进行发送。

通常,server会回给client三种类型的packet

i) OK Packet sql/protocol.cc::net_send_ok()

ii) ERROR Packet sql/protocol.cc::net_send_error_packet()

iii) result set PacketS 头包+字段包+EOF包+行包+EOF包

数据类型

mysql协议只有两种基本的数据类型,integer和string。

  • integer

integer包括fixed length integer和length encoded integer两种,对于length encoded integer,用的地方比较多,这里详细说明一下。
对于一个integer,我们按照如下的方式将其转成length encoded integer:
如果value < 251,使用1 byte
如果value >= 251 同时 value < 2 ** 16,使用fc + 2 byte
如果value >= 2 ** 16 同时 value < 2 ** 24,使用fd + 3 byte
如果value >= 2 ** 24 同时 value < 2 ** 64,使用fe + 8 byte
相应的,对于一个length encoded integer,我们可以通过判断第一个byte的值来转成相应的integer。

  • string

string包括:

fixed length string,固定长度string
null terminated string,以null结尾的string
variable length string,通过另一个值决定长度的string
length encoded string,通过起始length encoded integer决定长度的string
rest of packet string,从当前位置到包结尾的string

MySQLprotocol.png
MySQL协议分析.pdf

截包逐个分析
包功能结构,看上图(新窗口打开大图)更佳
协议分析,go实现proxy
MYSQL协议分析,分析较到位
官方协议说明
MySQL通讯协议研究1(基础知识)
MySQL协议分析

redis协议

标签: none

仅有一条评论

  1. 好久没来你博客了

添加新评论