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
编码过程, 记数值为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个字节;若后续未包含8个字节,则该协议包可能属于结束标志数据包(EOF_PACKET)。
1.2 String Types 字符串类型
(1)FixedLengthString
定长字符串,记为 string
(2)NulTerminatedString
由NUL标识结束的字符串, NUL即0x00,记为string
(3)VariableLengthString
动态长度字符串的长度基于其他字段或在运行时动态计算得出,并表示为string
(4)LengthEncodedString
采用长度编码表示法表示的字符串中,在开头有一个整型int
(5)RestOfPacketString
当某个字符串是协议包末尾的一个字段时, 那么该字符串的长度自然就等于包长减去当前位置, 并记为string
2.MySQL协议包
客户端或服务端要发消息给对方时:
1.把消息分成若干个长度小于 2^24-1(即16 M)的消息
2.给每个消息前面加一个4字节包头.
如下:
| Type | Name | Description |
|---|---|---|
| int<3> | payload_length | payload字段的长度 |
| int<1> | sequence_id | 序列号 |
| string | 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
指示操作失败的状态信息. Only when the CLIENT_PROTOCOL_41 capability feature is enabled, the message will include a SQL state value.
报文格式:

(3) EOF_Packet
When the CLIENT_PROTOCOL_41 capability flag is enabled, the EOF packet includes a warning count and status flags.
EOF报文用于标识由多个报文组成的报文簇的结束位置,在数据库系统中通常用于管理事务操作的安全性。例如,在MySQL服务器中,当客户端向其发送一个查询指令时(即发起一个查询请求),MySQL将按照预定顺序依次返回一系列相应的响应数据流(即分片)。
- ResultSetHeaderPacket — 在报文字段中携带了查询结果中的字段个数N以及还包括其他相关信息
2.FieldPacket * N -- N个FieldPacket,每一个都表示一个字段的定义
3.EOF Packet -- 表示字段定义的所有报文已发送完毕
4.RowDataPacket * M -- 每个报文表示一行数据
5.EOF Packet -- 表示行数据报文发送完毕。
报文格式:

End_of_File_PACKET和OK_PACKET均用于标识...查询结果的尾部数据包;自5.7.5版本起...该类型的数据包已不再被使用
上面的报文中涉及到的statu_flag取值及含义如下:

2.连接建立阶段报文
(1) Handshake Packet(Server - > Client)
当客户端发起与服务端的通信请求时,在建立通信链路完成之后(即TCP连接建立完成后),服务器会通过发送一份初始连接报文向客户端发起邀请(即握手)。这份初始连接报文包含了服务器的基本信息以及相应的权限标识(即capabilities flag)。其中关于权限标识的具体内容,请参阅此处以获取详细信息。
Java代码
- 协议版本号为1的[0a]格式
- 服务器端的版本号为NUL字符串
- 第4个连接ID字段
- 长度固定的字符串[8]用于身份验证插件的数据部分1
- 填充字段由一个固定值0x00组成
- 在服务器端决定权限标志位下2位的状态
- 当接收到的数据包中还有更多数据时:
a. 如果具备客户端插件中的授权标志位,则表示客户端插件的身份验证数据长度
b. 否则填充字段由一个固定值空字节组成
c. 设定标识符长度字段以记录身份验证插件数据的实际长度
d. 在具备客户端插件中的授权标志位时设定身份验证插件名称字段
(2)HandShake Response Packet(Client - > Server)
客户端接收到handshake packet后,向server发送出去一个response,其中包含客户端的权限标识符、用户名等信息.若handshake packet中权限标识符包含了client protocol 41标志位,则该客户端会发送handshake response 41;反之则会发送handshake response 320.鉴于大多数服务器已配备该功能,此处我们不再处理handshake response 320
HandShake Response41格式:
Java代码
- 客户端系统中设置了4个权限标志位(CLIENT_PROTOCOL_41),这些标志位始终被设置为已启用状态。
- 最大包大小设为4字节。
- 字符集长度设为1。
- 引用字符串(length of all key-values)字段全部置空后赋值给username变量。
- 当客户机具备AUTH-PLUGIN授权时,在连接数据库时会自动启用密码验证功能。
- 在客户机插件中定义了多个字符编码方案(encodings),其中包含ASCII编码方案。
3.普通请求/响应报文
在连接建立完成后,Client之后即可发送常规查询指令或其他操作指令给Server。接下来将详细讲解这些指令。
1.COM_SLEEP 请求
这个是Server内部的命令,不是客户端给服务端发的,忽略即可
Java代码
- 1 [00] COM_SLEEP
2.COM_QUIT 请求
当客户端要关闭连接时,发送该命令到Server
Java代码
- 1 [01] COM_QUIT
返回:要么是OK Packet,要么就连接关闭
3.COM_INIT_DB 请求
修改连接默认的schema
Java代码
- 1 [02] COM_INIT_DB
- string[EOF] schema name -- 数据库名
返回:OK Packet 或者ERR Packet
4.COM_QUERY 请求
提交普通查询请求时,请注意该查询属于即时执行类型。因此不需在编译阶段处理此命令。
Java代码
- 1 [03] COM_QUERY
- string[EOF] the query the server shall execute -- sql语句
返回:COM_QUERY_RESPONSE Packet
5.COM_QUERY_PACKET 响应
对于COM_QUERY这一查询指令生成的响应报文而言,在此过程中仅会输出对应的结果集合信息这一种情况
- Error Code Packets
- OK Message or OK Data Frame
- Common Query Result Set Packets -- 常见查询结果集
- Data Loading In-File Request Message or In-File Request Data Frame
6. Result Set Packet 响应 普通的查询响应也是一个逻辑上定义的报文,并且它由以下几个组成部分构成:它包括数据字段、字段值、元数据以及相关的元数据信息。
1.ResultSetHeaderPacket -- 仅由带有
- ColumnDefinitionPacket * N表示N个ColumnDefinitionPacket ,每一个ColumnDefinitionPacket表示一个字段的信息 ,其格式如下。
Java代码
以下是根据给定规则对原文的改写
以下是根据给定规则对原文的改写
以下是根据给定规则对原文的改写
以下是根据给定规则对原文的改写
以下是根据给定规则对原文的改写
以下是根据给定规则对原文的改写
以下是根据给定规则对原文的改写
以下是根据给定规则对原文的改写
以下是根据给定规则对原文的改写
以下是根据给定规则对原文的改写
以下是根据给定规则对原文的改写
以下是根据给定规则对原文的改写
以下是根据给定规则对原文的修改
- 当收到EOF包时表示所有ColumnDefinition包已发送完毕,接下来即将开始处理数据传输。
4.任意数量的RowDataPacket都有所对应的具体信息。每个RowDataPacket都对应一行数据。其中 NULL 值以字节 0xfb(即十进制 251)进行编码。具体格式请参考下文
Java代码
该字符串在第1个字段中的数据值为:...
该字符串在第2个字段中的数据值为:...
...
该字符串在第N个字段中的数据值为:...
- 结束标记包(EOF Packet),表示对应的Result Set已经结束。如果接收到的该数据包中包含了
SERVER_MORE_RESULT_EXISTS字段的标志位为真,则也即说明后续还会再发送一个Result Set Packets,请返回到最初步骤继续接收...
整个查询过程如下图:

7.COM_FIELD_LIST 请求
获取字段定义,5.7.11开始已弃用
Java代码
1 [04] COM Field List
2 null type string table -- 表名
3 string[EOF] field pattern 字段通配符
返回:COM_FIELD_LIST RESPONSE Packet
8.COM_FIELD_LIST 响应
COM_FIELD_LIST的响应报文,该报文是一个逻辑报文,其组成为以下一种:
1.ERR packet
2.任意个ColumnDefinitionPacket加一个EOFPacket
9.COM_CREATE_DB 请求
创建数据库请求
Java代码
- 1 [05] COM_CREATE_DB
- string[EOF] schema name -- 数据库名
返回:OK Packet或者ERR Packet
10.COM_DROP_DB 请求
删除数据库请求
Java代码
- 1 [06] COM_DROP_DB
- string[EOF] schema name -- 数据库名
返回:OK Packet 或者 ERR Packet
11.COM_REFRESH 请求
flush和reset...指令的命令实现自5.7.11版本起不再提供该功能,改用COM_QUERY函数来执行flush操作
Java代码
- 1 [07] COM_REFRESH
- 1 sub_command -- 命令,取值见下
sub_command取值:

返回:OK Packet或者ERR Packet
12.COM_SHUTDOWN 请求
关于关闭MySQL服务器的请求中提到5.7.9版本已被废弃使用8.0及以后版本则无法执行该命令建议更新至最新版本以避免相关问题
Java代码
- 1 [08] COM_SHUTDOWN
- if more data {
- 1 shutdown type
- }
shutdown type取值:

返回:OK Packet或者ERR packet
13.COM_STATISTICS 请求
显示人易读的MySQL服务器统计信息,在执行mysqladmin status时输入该命令
Java代码
- 1 [09] COM_STATISTICS
返回:string
14.COM_PROCESS_INFO 请求
请列出当前活跃的线程。当执行"显示过程列表"或发送"获取进程列表信息"命令时,请提供该命令。
Java代码
- 1 [0a] COM_PROCCESS_INFO
返回:ResultSetPacket 或者ERR Packet
15.COM_CONNECT 请求
mysql server 内部命令,5.7.11版本弃用,使用COM_QUERY替代
16.COM_PROCESS_KILL 请求
关闭连接
Java代码
- 1 [0c] COMMUNICATION PROCESS TERMINATED
- 4 connection identifier -- 连接标识符,在Handshake packet被传输过来
返回:OK Packet或者ERR Packet
16.COM_DEBUG 请求
When the COM_DEBUG trigger is activated, it generates a detailed report of the internal debug information, which is then outputted to the standard output of the mysql-server. The SUPER user must be granted access to perform this operation. issuing this command during a mysqladmin debug session will ensure that all operations are logged properly.
Java代码
- 1 [0d] COM_DEBUG
返回:EOF Packet或者ERR Packet
17.COM_PING 请求
心跳检测
Java代码
- 1 [0e] COM_PING
返回:OK Packet
18.COM_TIME
mysql server内部命令
19.COM_DELAYED_INSERT
mysql server内部命令
20.COM_CHANGE_USER 请求
更新当前连接中的用户信息并将其相关设置归零;操作包括更新相关参数、清除工作区表以及清除预先编译的SQL语句等步骤
Java代码
- COM_CHANGE_USER
- user_id
- 如果具备权限并成功建立安全连接{
- auth_response_length
- auth_response的内容
- }否则{
- auth_response为空字符串
- }
- schema_name为空字符串
- 当存在更多数据时{
- 第2个字符集
- 如果具备权限并成功加载客户端插件认证{
- auth插件名称为空字符串
- }否则{
- 如果具备权限并成功加载客户端连接属性{
- lenenc_int为所有键值对的数量
- lenenc_str表示各个键及其值的数量和长度
- 如果'长度'字段中存在更多数据,则表示有更多的键值对出现
- }
- }
21.COM_RESET_CONNECTION 请求
Re-set the session state; it is lighter in functionality compared to COMCHANGEUSER as it avoids closing and reopening the connection, while also avoiding the need for re-authentication.
Java代码
- 1 [1f] COM_RESET_CONNECTION
返回:OK Packet或者ERR Packet
22.COM_DAEMON 请求
mysql server内部命令
23.COM_STMT_PREPARE 请求
预编译语句,执行conn.preparedStatement(sql)时发送该命令
Java代码
- 1 the COM_STMT_PREPARE command
- string
query statement -- sql语句
返回:COM_STMT_PREPARED OK Packet或者Err Packet
24.COM_STMT_PREPARE Response 响应
预编译成功时的响应报文,时逻辑报文,其由多个报文组成:
1.第一个报文包含预编译成功信息,其格式如下:
Java代码
1状态项,[00]表示有效值--成功标志位
4statement_id--预先编译的标识符
字段数量为2--
参数数量为2--
保留状态始终设置为[空]--
警告数量设定为2--
如果上面的参数个数(记为N)大于0的话,则表示接下来会依次传输N个ColumnDefinitionPacket,并随后发送一个EOF Packet。
当字段数量为M且M>0时(即非零情况下),随后将发送M个ColumnDefinitionPacket以及一个EOF Packet
25.COM_STMT_SEND_LONG_DATA请求
当预编译阶段存在多个项时,
就需提供相应的请求信息,
这些请求都必须在COM_STMT.Execute之前的步骤中完成。
Java代码
- COM_STMT_SEND_LONG_DATA[18]
- statement-id -- 预编译确定的语句标识符
- param-id -- 参数标识符
- data -- 参数值
返回:无返回
26.COM_STMT_EXECUTE请求
执行预编译语句
Java代码
1个COM_STMT.Execute
4个stmt-id -- 语句ID
一个flags
四个iteration-count, 始终等于一
如果num-params大于零:
定义一个NULL-bitmap变量, 其长度为(num-params+7)除以八的结果
定义一个新的new-params-bound-flag变量
描述每个参数的数据类型, 长度为num-params乘以二的结果
给出每个参数的具体数值
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请求
关闭预编译语句,该请求无响应
Java代码
- 1 [19] COM_STMT_CLOSE
- 4 statement-id -- 预编译语句ID
29.COM_STMT_RESET请求
清除由COM_STMT_SEND_LONG_DATA传输的所有参数,并释放由COM_STMT.Execute打开的CURSOR
Java代码
- 1 [1a] COM_STMT_RESET
- 4 statement-id
返回:OK Packet或者ERR Packet
// TODO 未完待补充
