Advertisement

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

编码过程, 记数值为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

(2)NulTerminatedString

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

(3)VariableLengthString

动态长度字符串的长度取决于其他字段或其他因素,并且通过运行时计算得出的结果以string表示

(4)LengthEncodedString

采用长度编码的字符串表示法,则在字符串开头有一个整数类型的标识符int来指示后续字符串的实际长度;同时,在变量长度编码下进行操作时,默认将这些字符串标记为VariableLengthString,并用符号string表示。

(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

报文格式:

61f79a93aa853e2efc94ae23d38a4c96.png

判断时OK还是EOF规则:

OK: header = 0 and length of packet > 7

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

(2) ERR_Packet

该错误信息包含SQL状态值,当CLIENT_PROTOCOL_41处于启用状态时生效。

报文格式:

f57fe57e9fef498f1b04e21dd51dad45.png

(3) EOF_Packet

If CLIENT_PROTOCOL_41 is activated, when the EOF packet is received, it 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 -- 表示行数据报文发送完毕。

报文格式:

26e3003e386029ca988e9bc3ff64871d.png

EOF_Packet与OK_Packet都被设计用于标识查询结果的尾部数据包,在5.7.5版本中已经不再采用这种设计

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

106c01fe9b825b50fcbecc373f0902fb.png

2.连接建立阶段报文

(1) Handshake Packet(Server -> Client)

握手信息会在客户端尝试连接服务端时生成。当TCP连接建立之后, Server会向Client发送一个握手协议报文,其中包含了Server的相关信息以及权能标识。关于权能标识(capabilities flag),具体内容可参考链接获取详细解释

Java代码

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包时,它会生成一个响应并发送给服务器,并在响应中包含客户端的能力标志以及相关的信息。如果该Handshake包中的能力标志包含client_protocol_41字段,则对应的响应会被标记为Handshake Response41;否则则会被标记为Handshake Response320。然而,在我们的处理范围内,则不涉及Handshake Response320的情况。

HandShake Response41格式:

Java代码

4 capability flags, CLIENT_PROTOCOL_41 always set -- 客户端的权能标识

4 max-packet size -- 最大包大小

1 character set -- 字符集

string[23] reserved (all [0]) -- 保留,总是0

string[NUL] username -- 用户名

当具备某种能力时,在满足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内部的命令,不是客户端给服务端发的,忽略即可

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请求的报文仅作为一个逻辑层面的结构存在,并由以下几种类型构成

ERR Packet

OK Packet

ResultSet Packet -- 普通查询结果

LOAD DATA INFILE REQUEST Packet

6.ResultSetPacket 响应

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

  1. 该数据包仅包含一个整数(标记为N变量)代表结果字段的数量以及一个8-byte大小的附加信息块

第2部分包含N个ColumnDefinitionPacket(其中N为具体数值),每个ColumnDefinitionPacket代表一个字段的相关信息。

Java代码

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

}

  1. EOF包标识所有ColumnDefinition包已全部传输完毕;接下来将对数据进行处理。

多个RowDataPacket分别对应一行数据信息,在其中的Null字段采用0xfb(251)进行编码表示

Java代码

lenenc_str field1's value -- 第一个字段的值

lenenc_str field2's value -- 第二个字段的值

...

lenenc_str fieldN's value -- 第N个字段的值

第5个EOF包表明该ResultSetPacket已结束。如果此包中包含 SERVER_MORE_RESULT_EXISTS字段,则说明接下来还会有一个新的 ResultSetPacket出现,并将从头开始接收数据。

整个查询过程如下图:

14e03abc2c545e2979f05998c2f5842f.png

7.COM_FIELD_LIST 请求

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

Java代码

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 请求

创建数据库请求

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操作,并执行相应的flush指令。

Java代码

1 [07] COM_REFRESH

1 sub_command -- 命令,取值见下

sub_command取值:

a8f0c11fd649f958bda95d0c63ba0ef7.png

返回:OK Packet或者ERR Packet

12.COM_SHUTDOWN 请求

提交用于关闭MySQL服务器的请求,在版本5.7.9及以后将不再支持该功能,在8.0版本及以后将完全移除该命令,在运行mysqladmin shutdown指令时需注意此事项

Java代码

1 [08] COM_SHUTDOWN

if more data {

1 shutdown type

}

shutdown type取值:

de00f94399acb87da60311b6b55f53dd.png

返回:OK Packet或者ERR packet

13.COM_STATISTICS 请求

输出MySQL服务器运行状态信息,在执行MySQL管理员status命令时显示该统计结果。

Java代码

1 [09] COM_STATISTICS

返回:string

14.COM_PROCESS_INFO 请求

Obtain a list of active threads. When executing the commands 'mysql -k show processlist' or 'mysqladmin -k show processlist', send this command.

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] COM_PROCCESS_KILL

4 connection id -- 连接ID,这个是在HandShake Packet传过来的

返回:OK Packet或者ERR Packet

16.COM_DEBUG 请求

When the COM_DEBUG trigger is activated, it dumps internal debug information to the stdout of the mysql-server. The SUPER user privilege is necessary for this function. Issue the MySQL Administration tool's debug command when needed.

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 请求

修改当前连接的用户并重新设置其连接状态, 包括与该用户的关联信息, 同时也涉及user variables、临时表和预编译语句等技术细节.

Java代码

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 请求

Reinitialize the session state. Compared to COMCHANGEUSER, this approach is lighter in terms of connection management as it avoids closing and reopening the connection and does not require 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 status, [00]=OK --成功标志

4 statementId -- 预编译的语句ID

2 number of columns -- 字段个数

2 number of params -- 参数个数

1 reserved, always 00 -- 保留

2 number of warnings -- 警告个数

当参数个数(记为N)为非零值时,将包含N个ColumnDefinitionPacket以及一个EOF Packet。

当某个字段集合(标记为M)的数量超过零时,将被发送包括M个ColumnDefinitionPacket和一个EOF包。

25.COM_STMT_SEND_LONG_DATA请求

将参数值传递至预先编译的语句。预先编译中有多少个,则需要相应地发送该请求,并且所有请求必须在COM_STMT.Execute之前完成。

Java代码

1 [18] COM_STMT_SEND_LONG_DATA

4 statement-id -- 预编译语句ID

2 param-id -- 参数ID

n data -- 参数值

返回:无返回

26.COM_STMT_EXECUTE请求

执行预编译语句

Java代码

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

n value of each parameter

flags取值:

844bb05ce48546aaf3483afa215e5a2f.png

返回: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所打开的游标

Java代码

1 [1a] COM_STMT_RESET

4 statement-id

返回:OK Packet或者ERR Packet

全部评论 (0)

还没有任何评论哟~