`

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 未完待补充

0
1
分享到:
评论

相关推荐

    Mycat2是Mycat社区开发的一款分布式关系型数据库(中间件) 它支持分布式SQL查询,兼容MySQL通信协议

    Mycat2是Mycat社区开发的一款分布式关系型数据库(中间件)。它支持分布式SQL查询,兼容MySQL通信协议,以Java生态支持多种后端数据库,通过数据分片提高数据查询处理能力

    MySQL通讯协议分析

    MySQL作为一款广泛使用的开源关系型数据库管理系统,在其内部实现了一套高效且稳定的通信协议——MySQL通信协议,用于客户端和服务端之间的数据交换。这一协议不仅定义了客户端和服务端如何进行握手连接、认证、执行...

    MySQL的协议分析pdf

    本PDF文档“MySQL的协议分析”深入探讨了MySQL通信协议的核心概念和工作原理,这对于理解数据库操作背后的机制、优化数据库性能以及进行数据库相关的开发和调试具有重要意义。 MySQL协议是基于TCP/IP的,它规定了...

    mysql通讯协议介绍.doc

    MySQL通信协议是MySQL服务器与客户端之间进行数据交互的规则集,它是MySQL数据库系统的核心组成部分,确保了客户端应用程序能够正确地发送查询和其他命令到服务器,并接收响应。本文将深入解析MySQL通信协议中的几个...

    MySQL.zip_MYSQL_MySQL抓包数据协议分析_mysql审计_抓包_数据审计

    5. 审计和监控:通过对MySQL通信协议的抓包分析,可以实现对数据库操作的全面审计,包括查看谁在何时执行了哪些操作,这有助于追踪潜在的安全威胁和违规行为。此外,结合日志记录和专门的审计插件,可以实现更高级别...

    MySQL 和 PostgreSQL 协议解析和对比.pdf

    MySQL 和 PostgreSQL 的通信协议层处理在双方的官方文档中都有详细介绍。 初始化启动 初始化启动两者的客户端和服务端之间的通信都是基于 TCP 协议,在三次握手后正式建立连接。 MySQL 通信协议 在 MySQL 中,...

    mysql 5.5版 头文件(mysql.h等)

    4. `mysql_com.h`:包含了MySQL通信协议的相关定义,如MySQL命令类型、状态变量、预处理语句和结果集的定义。这些定义对于理解MySQL如何通过网络传输数据至关重要。 5. `mysql_time.h`:提供了日期和时间类型,如`...

    Go-go-mysql-一个Go工具集用于处理MySQL协议和复制

    它通过解析和构建TCP/IP报文,实现了对MySQL通信协议的完整封装。这使得开发者可以方便地创建自定义的MySQL客户端或中间件,而无需深入了解复杂的MySQL网络协议细节。 ### 2. 数据库操作 库中包含了用于执行SQL...

    mysql自带的头文件

    1. `mysql_com.h`:包含了MySQL通信协议相关的定义,如错误代码、状态消息等。 2. `mysql_time.h`:提供了日期和时间类型以及相关的函数,用于处理`MYSQL_TIME`结构体。 3. `mysql_rowbuf.h`:包含关于预处理语句...

    MySQL协议的抓包工具源代码.zip

    本压缩包文件包含了实现这一功能的源代码,可以帮助我们深入了解MySQL通信协议的工作原理。 MySQL协议是基于TCP/IP的,它定义了服务器和客户端之间数据传输的格式和步骤。在MySQL协议中,每个交互都由一连串的“包...

    vc连接mysql中所需要的mysql头文件

    `mysql_com.h`提供了MySQL通信协议的定义,包括各种状态和错误代码。这个头文件通常在`mysql.h`中被包含,但如果你需要深入理解MySQL的网络协议,可能需要直接引用。 `mysql_version.h`包含了MySQL的版本信息,例如...

    mysql开发用头文件和库文件(mysql.h、libmyhsql等)

    除了`mysql.h`和`libmysqlclient`,MySQL还提供了其他头文件和库,如`mysql_com.h`(包含了MySQL通信协议的基本定义)、`mysql_error.h`(错误代码和消息)、`mysql_time.h`(日期和时间类型),以及`libmysql.lib`...

    mysql头文件include打包

    4. `mysql_com.h`:包含了所有的MySQL通信协议常量和枚举,如命令类型和状态标志。 5. `mysql_time.h`:提供了日期和时间相关的数据结构和函数,如`MYSQL_TIME`,用于处理日期和时间的输入/输出。 6. `my_config.h...

    C++调用Mysql的所有组件

    - **mysql_com.h**: 包含了MySQL通信协议相关的定义,比如数据包的格式、状态码等,对于自定义通信协议或者扩展功能的开发者来说较为有用。 - **mysql_time.h**: 提供了表示日期和时间的结构体,如`MYSQL_TIME`,...

    C++操作mysql数据库之配置篇

    `mysql_com.h`包含了MySQL通信协议的相关定义,包括各种命令和响应的结构体,以及用于解析和构建这些消息的函数。这个头文件中的内容对于理解MySQL客户端和服务器之间如何交换数据至关重要。 `mysql_time.h`提供了...

    C连接MYSQL5.1所需要的库文件

    - **mysql_com.h**:包含MySQL通信协议的定义,用于建立和管理与服务器的连接。 - **mysql_time.h**:包含了MySQL处理日期和时间类型的数据结构和函数。 - **my_alloc.h**:定义了MySQL自定义的内存分配函数,如my_...

    一个工作在nginx_tcp中的集群聊天服务器,数据库用mysql部署,网络通信采用muduo和json消息作为通信协议.zip

    一个工作在nginx_tcp中的集群聊天服务器,数据库用mysql部署,网络通信采用muduo和json消息作为通信协议 一个工作在nginx_tcp中的集群聊天服务器,数据库用mysql部署,网络通信采用muduo和json消息作为通信协议 一个...

    MySQL Connector.C 6.1.rar

    MySQL Connector/C是MySQL数据库的一种客户端库,它实现了MySQL通信协议,使得开发者可以使用C语言编写应用程序来连接和操作MySQL服务器。它提供了API函数,包括连接、查询、事务处理、游标操作等功能,覆盖了...

    mysql-connector-c-6.1.5

    - `protocol.c`、`net_serv.c`:实现MySQL通信协议和网络服务,处理客户端与服务器间的通信。 4. **基本用法示例** ```c #include &lt;mysql.h&gt; int main() { MYSQL *conn; conn = mysql_init(NULL); if (!...

    MySql数据库驱动包.zip

    4. **类型4(完全Java驱动,也称为协议驱动)**:mysql-connector-java-8.0.12.jar可能属于这一类,它使用Java实现MySQL通信协议,无需中间件或本地库,提供了更快的速度和更好的性能。 对于mysql-connector-java-...

Global site tag (gtag.js) - Google Analytics