MySQL协议分析
本来看MySQL协议是要做一个skynet的lua c库的,今天群里有人实现了,主要是根据openresty/lua-resty-mysql改的,之前工作老停留在协议内容上,不过也好,充分学些了一些MySQL协议。
同时这个项目也值得关注OpenResty。
一次正常的过程如下
- 三次握手建立tcp连接
- 建立MySql连接
a) 服务端往客户端发送握手初始化包(Handshake Initialization Packet)
b) 客户端往服务端发送验证包(Client Authentication Packet)
c) 服务端往客户端发送成功包 - 客户端与服务端之间交互
a) 客户端往服务端发送命令包(Command Packet)
b) 服务端往客户端发送回应包(OK Packet, or Error Packet, or Result Set Packet) - 断开MySql连接
a) 客户端往服务端发送退出命令包 - 四次握手断开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
截包逐个分析
包功能结构,看上图(新窗口打开大图)更佳
协议分析,go实现proxy
MYSQL协议分析,分析较到位
官方协议说明
MySQL通讯协议研究1(基础知识)
MySQL协议分析
好久没来你博客了