MySQL 通信协议

技术标签: mysql  通信协议

 MySQL 通信协议介绍

 

1、数据类型

了解MySQL协议包之前必需先知道其数据类型

 

 1.1 Integer Types 整数类型

(1)定长整型

固定长度, 小端编码, 有下面几种(括号内的代表所占字节数):

int<1>

int<2>

int<3>

int<4>

int<6>

int<8>

 

(2)变长整型

可能长度为1, 3, 4, 9 个字节, 实际长度取决于数值的大小.记为 int<lenenc>

 

编码过程, 记数值为N:

1.若 N < 251, 则编码为单字节

2.若 251 <= N < 2^16, 则编码为 0xfc + 2-byte integer

3.若 2^16 <= N < 2^24, 则编码为 0xfd + 3-byte integer

4.若 2^24 <= N < 2^64, 则编码为0xfe + 8-byte integer

 

解码过程, 先看第一个字节, 记其值为N1,

1.若 N1 <= 0xfb, 则说明该整数就是N1

2.若 N1 = 0xfc,则说明接下来2字节也是该整数的部分, 取出加上0xfc即为原数值

3.若 N1 = 0xfd, ...

4.若 N1 = 0xfe, ...

 

值得注意的是, 当协议包的第一个字节为0xfe时, 应该检查接下来是否有8个字节, 若没有则说明该协议包可能是EOF_PACKET

 

1.2 String Types 字符串类型

 

(1)FixedLengthString

定长字符串,记为 string<fix>

 

(2)NulTerminatedString

由NUL标识结束的字符串, NUL即0x00,记为string<NUL>

 

(3)VariableLengthString

变长字符串, 长度由别的其它字段决定或者运行时动态计算出来的,记为string<var>

 

(4)LengthEncodedString

长度编码的字符串, 即其前面有个整型int<lenenc>说明接下来的字符串的长度, 起始就是VariableLengthString,记为string<lenenc>

 

(5)RestOfPacketString

若一个字符串是一个协议包的最后一个字段, 那该字符串的长度当然就等于包长 - 当前位置,记为string<EOF>

 

2.MySQL协议包

客户端或服务端要发消息给对方时:

1.把消息分成若干个长度小于 2^24-1(即16 M)的消息

2.给每个消息前面加一个4字节包头.

如下:

Type Name Description
int<3> payload_length payload字段的长度
int<1> sequence_id ***
string<var> payload payload包体

 

例如CMD_QUIT的整包字节序列为:01 00 00 00 01

 

 

 1.通用响应报文

 

(1) OK_Packet

表示操作成功的报文,5.7开始用该报文替代EOF_Packet

 

 报文格式:

 

判断时OK还是EOF规则:

OK: header = 0 and length of packet > 7

EOF: header = 0xfe and length of packet < 9

 

(2) ERR_Packet

表示操作失败的报文. It contains a SQL state value if CLIENT_PROTOCOL_41 is enabled.

 

报文格式:

 

 (3) EOF_Packet

If CLIENT_PROTOCOL_41 is enabled, the EOF packet contains a warning count and status flags.

 EOF报文用来表示多个报文组成的一个报文簇的结束,比如当客户端发送查询命令到mysql server时,mysql会按顺序回复以下报文:

1.ResultSetHeaderPacket  --报文中携带了查询结果包含的字段的个数N,以及其它一些信息

2.FieldPacket * N -- N个FieldPacket,每一个都表示一个字段的定义

3.EOF Packet -- 表示字段定义的所有报文已发送完毕

4.RowDataPacket * M -- 每个报文表示一行数据

5.EOF Packet -- 表示行数据报文发送完毕。

 

报文格式:


 

EOF_Packet和OK_Packet 都是用来表示一个query的结果的尾包,5.7.5版本EOF_Packet就不在使用了

 

上面的报文中涉及到的statu_flag取值及含义如下:

 

 

 

2.连接建立阶段报文

 

(1) Handshake Packet(Server -> Client)

握手报文,当客户端连接服务端时,当TCP连接建立完成后,Server会主动向Client发送一个握手协议报文,里面携带了Server的相关信息和权能标识,关于权能标识(capabilities flag),具体可以去这里

 

 

1              [0a] protocol version -- 协议版本
string[NUL]    server version -- Server版本
4              connection id
string[8]      auth-plugin-data-part-1
1              [00] filler -- 填充,总是0x00
2              capability flags (lower 2 bytes) --Server权能标识
  if more data in the packet:
1              character set -- 连接所使用的字符集
2              status flags
2              capability flags (upper 2 bytes)
  if capabilities & CLIENT_PLUGIN_AUTH {
1              length of auth-plugin-data
  } else {
1              [00]
  }
string[10]     reserved (all [00])
  if capabilities & CLIENT_SECURE_CONNECTION {
string[$len]   auth-plugin-data-part-2 ($len=MAX(13, length of auth-plugin-data - 8))
  if capabilities & CLIENT_PLUGIN_AUTH {
string[NUL]    auth-plugin name
  }

 

 

(2)HandShake Response Packet(Client -> Server)

客户端收到Handshake Packet后,生成一个Response并发给Server,里面携带客户端的权能标识,用户名等相关的信息,如果Handshake Packet中的权能标识中带有client_protocol_41标识位,那么客户端将生成的Response为HandShake Response41,否则生成的为HandShake Response320,我们这里就不管HandShake Response320,因为现在的Server基本都会支持这个

 

HandShake Response41格式:

 

4              capability flags, CLIENT_PROTOCOL_41 always set -- 客户端的权能标识
4              max-packet size -- 最大包大小
1              character set -- 字符集
string[23]     reserved (all [0]) -- 保留,总是0
string[NUL]    username -- 用户名
  if capabilities & CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA { -- 看了mycat的源码才知道,这个其实是密码
lenenc-int     length of auth-response
string[n]      auth-response
  } else if capabilities & CLIENT_SECURE_CONNECTION {
1              length of auth-response
string[n]      auth-response
  } else {
string[NUL]    auth-response
  }
  if capabilities & CLIENT_CONNECT_WITH_DB { -- 连接默认数据库名
string[NUL]    database
  }
  if capabilities & CLIENT_PLUGIN_AUTH {
string[NUL]    auth plugin name
  }
  if capabilities & CLIENT_CONNECT_ATTRS {
lenenc-int     length of all key-values
lenenc-str     key
lenenc-str     value
   if-more data in 'length of all key-values', more keys and value pairs
  }

 

 

3.普通请求/响应报文

在连接建立后,Client就可以发送普通的查询或者其它命令给Server了,下面对这些命令进行介绍

 

1.COM_SLEEP 请求

这个是Server内部的命令,不是客户端给服务端发的,忽略即可

 

1              [00] COM_SLEEP

 

 

 

2.COM_QUIT 请求

当客户端要关闭连接时,发送该命令到Server

 

1              [01] COM_QUIT

 

返回:要么是OK Packet,要么就连接关闭

 

3.COM_INIT_DB 请求

修改连接默认的schema

 

1              [02] COM_INIT_DB
string[EOF]    schema name -- 数据库名

 

返回:OK Packet 或者ERR Packet

 

4.COM_QUERY 请求

发送普通查询请求,这个查询是立即执行的,因此预编译不是发这个命令的

 

1              [03] COM_QUERY
string[EOF]    the query the server shall execute -- sql语句

 

返回:COM_QUERY_RESPONSE Packet

 

5.COM_QUERY_PACKET 响应

COM_QUERY的响应报文,该报文只是个逻辑上的报文,其组成为以下几个中的一个:

  • ERR Packet
  • OK Packet
  • ResultSet Packet -- 普通查询结果
  • LOAD DATA INFILE REQUEST Packet

6.ResultSetPacket 响应
普通查询结果,也是一个逻辑上的报文,其由以下部分组成:

1.ResultSetHeaderPacket -- 只包含一个int<lenenc>的整数(记为N,表示结果字段的个数)和一个8字节的extra附加信息

2.ColumnDefinitionPacket * N -- N个ColumnDefinitionPacket ,每个ColumnDefinitionPacket表示一个字段的信息,其格式如下:

lenenc_str     catalog
lenenc_str     schema
lenenc_str     table
lenenc_str     org_table
lenenc_str     name
lenenc_str     org_name
lenenc_int     length of fixed-length fields [0c]
2              character set
4              column length
1              type
2              flags
1              decimals
2              filler [00] [00]
  if command was COM_FIELD_LIST {
lenenc_int     length of default-values
string[$len]   default values
  }

 3.EOF Packet 表示所有ColumnDefinitionPacket都发送完了,接下来将发行数据了 

4.任意个RowDataPacket,每一个代表一行数据,其中NULL用0xfb(251)表示,其格式如下:

lenenc_str        field1's value -- 第一个字段的值
lenenc_str        field2's value -- 第二个字段的值
...
lenenc_str        fieldN's value -- 第N个字段的值

 5.EOF Packet,表示ResultSetPacket完毕,若此包中的SERVER_MORE_RESULT_EXISTS被设置,则则说明接下来还有ResultSetPacket,又回到第一步开始接收...

 

整个查询过程如下图:

 

 

 

7.COM_FIELD_LIST 请求

获取字段定义,5.7.11开始已弃用

 

1              [04] COM_FIELD_LIST
string[NUL]    table -- 表名
string[EOF]    field wildcard 字段通配符

 

返回:COM_FIELD_LIST RESPONSE Packet

 

 

8.COM_FIELD_LIST 响应

COM_FIELD_LIST的响应报文,该报文是一个逻辑报文,其组成为以下一种:

1.ERR packet

2.任意个ColumnDefinitionPacket加一个EOFPacket

 

9.COM_CREATE_DB 请求

创建数据库请求

 

1              [05] COM_CREATE_DB
string[EOF]    schema name -- 数据库名

 返回:OK Packet或者ERR Packet

 

10.COM_DROP_DB 请求

删除数据库请求

 

1              [06] COM_DROP_DB
string[EOF]    schema name -- 数据库名

 

返回:OK Packet 或者 ERR Packet

 

11.COM_REFRESH 请求

Flush ... 和RESET ... 语句的实现命令,从5.7.11版本开始已弃用,改用COM_QUERY,执行FLUSH语句或者

 

1              [07] COM_REFRESH
1              sub_command -- 命令,取值见下

 sub_command取值:


 

 返回:OK Packet或者ERR Packet

 

 

12.COM_SHUTDOWN 请求

 shutdown mysql server的请求,5.7.9已弃用,8.0已移除,执行mysqladmin shutdown时发送该命令

 

1              [08] COM_SHUTDOWN
  if more data {
1              shutdown type
  }

 

 shutdown type取值:

 

返回:OK Packet或者ERR packet

 

13.COM_STATISTICS 请求

获取human readable的mysql server统计信息,执行mysqladmin status时发送该命令

 

 

1              [09] COM_STATISTICS

 

 

返回:string<EOF>

 

 

 14.COM_PROCESS_INFO 请求

  get a list of active threads,执行show processlist 或者 mysqladminproesslist时发送该命令

 

 

1              [0a] COM_PROCCESS_INFO

 

 

返回:ResultSetPacket 或者ERR Packet

 

15.COM_CONNECT 请求

mysql server 内部命令,5.7.11版本弃用,使用COM_QUERY替代

 

16.COM_PROCESS_KILL 请求

关闭连接

 

 

1              [0c] COM_PROCCESS_KILL
4              connection id -- 连接ID,这个是在HandShake Packet传过来的

 

 

返回:OK Packet或者ERR Packet

 

 

16.COM_DEBUG 请求

COM_DEBUG triggers a dump on internal debug info to stdout of the mysql-server.The SUPER privilege is required for this operation.执行mysqladmin debug时发送该命令

 

 

1              [0d] COM_DEBUG

 

 

返回:EOF Packet或者ERR Packet

 

17.COM_PING 请求

心跳检测

 

 

1              [0e] COM_PING

 

 

返回:OK Packet

 

18.COM_TIME 

mysql server内部命令

 

19.COM_DELAYED_INSERT

mysql server内部命令

 

20.COM_CHANGE_USER 请求

更改当前连接的用户并重置连接状态,包括user variables、临时表和预编译语句等等...

 

 

1              [11] COM_CHANGE_USER
string[NUL]    user
  if capabilities & SECURE_CONNECTION {
1              auth-response-len
string[$len]   auth-response
  } else {
string[NUL]    auth-response
  }
string[NUL]    schema-name
  if more data {
2              character-set
    if capabilities & CLIENT_PLUGIN_AUTH {
string[NUL]    auth plugin name
    }
    if capabilities & CLIENT_CONNECT_ATTRS) {
lenenc-int     length of all key-values
lenenc-str     key
lenenc-str     value
   if-more data in 'length of all key-values', more keys and value pairs
    }
  }

 

 

 

21.COM_RESET_CONNECTION 请求

Resets the session state; more lightweight than COM_CHANGE_USER because it does not close and reopen the connection, and does not re-authenticate

 

 

1              [1f] COM_RESET_CONNECTION

 

 

返回:OK Packet或者ERR Packet

 

22.COM_DAEMON 请求

mysql server内部命令

 

23.COM_STMT_PREPARE 请求

预编译语句,执行conn.preparedStatement(sql)时发送该命令

 

 

1                  the COM_STMT_PREPARE command 
string<EOF>        query statement -- sql语句

 

 

返回:COM_STMT_PREPARED OK Packet或者Err Packet

 

24.COM_STMT_PREPARE Response 响应

预编译成功时的响应报文,时逻辑报文,其由多个报文组成:

1.第一个报文包含预编译成功信息,其格式如下:

 

1        status, [00]=OK --成功标志
4        statementId -- 预编译的语句ID
2        number of columns -- 字段个数
2        number of params -- 参数个数
1        reserved, always 00 -- 保留
2        number of warnings -- 警告个数

 

2.如果上面的参数个数(记为N)大于0的话,那么接下来会有N个ColumnDefinitionPacket加上一个EOF Packet会被发送

 

3.如果上面的字段个数(记为M)大于0的话,那么接下来会有M个ColumnDefinitionPacket加上一个EOF Packet会被发送

 

 

 

25.COM_STMT_SEND_LONG_DATA请求

发送参数值给预编译语句,预编译中有几个?就得发几个该请求,并且都得在COM_STMT_EXECUTE之前发送

 

1              [18] COM_STMT_SEND_LONG_DATA
4              statement-id -- 预编译语句ID
2              param-id -- 参数ID
n              data -- 参数值

 

返回:无返回

 

26.COM_STMT_EXECUTE请求

执行预编译语句

1              [17] COM_STMT_EXECUTE
4              stmt-id -- 语句ID
1              flags
4              iteration-count, always 1
if num-params > 0:
n              NULL-bitmap, length: (num-params+7)/8
1              new-params-bound-flag
if new-params-bound-flag == 1:
n              type of each parameter, length: num-params * 2
n              value of each parameter

flags取值:

 

 

 

返回:COM_STMT_EXECUTE Response

 

27.COM_STMT_EXECUTE Response响应

 COM_STMT_EXECUTE 的响应报文,是下面三者之一:

1.OK Packet -- 执行update时

2.Err Packet

3.Binary Protocol ResultSet Packet --执行查询时

 

Binary Protocol ResultSet 

binary protocol result和之前讲的ResultSetPacket相似,

 

28.COM_STMT_CLOSE请求

 关闭预编译语句,该请求无响应

 

    1              [19] COM_STMT_CLOSE
    4              statement-id -- 预编译语句ID

 

 

29.COM_STMT_RESET请求

 清空由COM_STMT_SEND_LONG_DATA发送的所有参数值,并关闭由COM_STMT_EXECUTE打开的CURSOR

 

    1              [1a] COM_STMT_RESET
    4              statement-id

 

返回:OK Packet或者ERR Packet

 

// TODO 未完待补充

来源:网络


智能推荐

ModBus通信协议

ModBus通信协议 1 1. 主从模式 RS-485上的软件层协议ModBus主要依赖于主从模式。主从模式是指在半双工通讯方式上,2个或者2个以上的设备组成的通讯系统中: (1) 至少且只有一个主机,其他的都是从机 (2) 不管任何时候,从机都不能主动向主机发送数据 (3) 主机具有访问从机的权限,从机不可以主动访问从机,任何一次数据交换,都要由主机发起 (4)不管是主机还是从机,系统一旦上电,...

通信协议

通信协议        由于没有存储共享器,分布式系统中的所有通信都是基于底层消息交换的。如果进程A要与进程B通信,A必须首先在自己的地址空间中生成该消息,再执行一个系统调用,通知操作系统将该消息通过网络发送给B。   为了使一组计算机能够通过网络相互通信,它们必须使用相同的协议。可以把协议划分为两大类。   一类是面向连接协议,使用这种协议,消息发送方和接...

spi通信协议

SPI同步串行外设接口   序号 PIN 定义 1 CS 从机选择信号 2 SCK 串行时钟线(由主机提供) 3 MOSI 主机输出->从机输入 4 MISO 主机输入<-从机输出 表一 总线引脚定义 图一 SPI通信示意图   SPI时序 SPI时序共有4中模式,由CPHA,CPOL来确定   参数 0 1 CPOL SCK空闲时为低电平 SCK空闲时为...

SPI通信协议

    SPI,SPI 全称是 Serial Perripheral Interface,也就是串行外围设备接口。 SPI 是 Motorola 公司推出的一种同步串行接口技术,是一种高速、全双工的同步通信总线, SPI 时钟频率相比 I2C 要高很多,最高可以工作在上百 MHz。 SPI 以主从方式工作,通常是有一个主设备和一个或多个从设备,一般 SPI 需要4 根线,但是也...

IIC通信协议

IIC 通信协议 I2C(IIC,Inter-Integrated Circuit),数据线SDA(data)和时钟SCL(clock)构成的串行总线,双向传送。 高速IIC总线一般可达400kbps以上。 IIC是半双工通信方式。 时序图 主机:起始信号—–>第一位——>第二位———> &hel...

猜你喜欢

SPI通信协议

什么是SPI? SPI, Serial Perripheral Interface, 串行外围设备接口, 是 Motorola 公司推出的一种同步串行接口技术,是一种高速的,全双工,同步的通信总线。SPI 总线在物理上是通过接在外围设备微控制器(PICmicro) 上面的微处理控制单元 (MCU) 上叫作同步串行端口(Synchronous Serial Port) 的模块(Module)来实现的...

UART通信协议

硬件连接:通常有三根线,分别为TXD,RXD,GND。通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),通常称作UART。UART通信在工作中相当常见,项目中需要生成uart信号,在博客中记录下。uart是异步通信,因为它只有一根线就可以数据的通信。不像SPI,I2C等同步传输信号。所以串口的传输速度和其它协议的速度相比是比较慢的。下面具...

USB 通信协议

USB通信协议概述 一、SUB概述         USB协议有两种:USB1.1和USB2.0。(现在有3.0了)         USB2.0和USB1.1完全兼容。USB1.1支持的 数据传输率为12Mbps和1.5Mbps(用于慢 速外设),USB2....

PID算法控制平衡小车速度

1.平衡小车速度控制:   平衡小车在平衡的前提下,应该想办法让他直立行走,也就是下面要讲的在直立控制下给予小车速度达到速度控制 速度控制应该控制的是倾斜角从而触发直立控制达到移动的目的,小车运动的速度和倾斜角成正比,向前运动时车身往前倾斜,角度越大速度越大。 (1)我们设置小车的目标速度为0,先关闭之前调试好的直立控制 (2)积分项的偏差由积分得到,所以积分控制和比例控制的极性相同,查...

How Touch Screen Monitors Work

2019独角兽企业重金招聘Python工程师标准>>> Brief History In 1972, a scientist at CERN - The European Organization for Nuclear Research - proposed the idea for the world’s first capacitive touch screen...

问答精选

How to display page using sinatra and rspec

I'm using Rspec to test a Sinatra application. Sometimes things go wrong (tests doesn't pass) and I would like to be able to see the page, without much effort(equivalent of 'Then show me the page' in ...

My where statement with a JSON_extract function on a nullable column is confirmed when said column's value is NULL?

I have a where statement with a JSON_extract method in it. The JSON_extract uses a nullable column called new_value or old_value. The check works if the column contains a JSON string, but when the col...

How can I get an object inside an array in JavaScript?

I have a for loop and I would like to tap into an object inside the array I am looping. Specifically I would like to tap into the "Name" section of my objects to only console.log the names, ...

Why is the exception NO_DATA_FOUND not being triggered?

So the problem i am having is that if i execute the following procedure and the cursor doesnt find the parameter being passed, it continues to execute the block (insert statement) but instead of throw...

how to differentiate media screen for ipad and ipad pro in css

so, I want to make a responsive loader (image). that the position always in the middle of the screen and the width always follow the size of the screen. So, I used @media only screen for do that, and ...

相关问题

相关文章

热门文章

推荐文章

相关标签

推荐问答