MySQL协议分析

1 交互过程
MySQL客户端与服务器的交互主要分为两个阶段:握手认证阶段和命令执行阶段。
1.1 握手认证阶段
握手认证阶段为客户端与服务器建立连接后进行,交互过程如下:
- 服务器 -> 客户端:握手初始化消息
- 客户端 -> 服务器:登陆认证消息
- 服务器 -> 客户端:认证结果消息
1.2 命令执行阶段
客户端认证成功后,会进入命令执行阶段,交互过程如下:
- 客户端 -> 服务器:执行命令消息
- 服务器 -> 客户端:命令执行结果
MySQL客户端与服务器的完整交互过程如下:

2 基本类型
2.1 整型值
MySQL报文中整型值分别有1、2、3、4、8字节长度,使用小字节序传输。
2.2 字符串(以NULL结尾)(Null-Terminated String)
字符串长度不固定,当遇到'NULL'(0x00)字符时结束。
2.3 二进制数据(长度编码)(Length Coded Binary)
数据长度不固定,长度值由数据前的1-9个字节决定,其中长度值所占的字节数不定,字节数由第1个字节决定,如下表:
| 第一个字节值 | 后续字节数 | 长度值说明 |
|---|---|---|
| 0-250 | 0 | 第一个字节值即为数据的真实长度 |
| 251 | 0 | 空数据,数据的真实长度为零 |
| 252 | 2 | 后续额外2个字节标识了数据的真实长度 |
| 253 | 3 | 后续额外3个字节标识了数据的真实长度 |
| 254 | 8 | 后续额外8个字节标识了数据的真实长度 |
2.4 字符串(长度编码)(Length Coded String)
字符串长度不固定,无'NULL'(0x00)结束符,编码方式与上面的 Length Coded Binary 相同。
3 报文结构
报文分为消息头和消息体两部分,其中消息头占用固定的4个字节,消息体长度由消息头中的长度字段决定,报文结构如下:

3.1 消息头
3.1.1 报文长度
用于标记当前请求消息的实际数据长度值,以字节为单位,占用3个字节,最大值为 0xFFFFFF,即接近 16 MB 大小(比16MB少1个字节)。
3.1.2 序号
在一次完整的请求/响应交互过程中,用于保证消息顺序的正确,每次客户端发起请求时,序号值都会从0开始计算。
3.2 消息体
消息体用于存放请求的内容及响应的数据,长度由消息头中的长度值决定。
4 报文类型
4.1 登陆认证交互报文
4.1.1 握手初始化报文(服务器 -> 客户端)

服务协议版本号:该值由 PROTOCOL_VERSION 宏定义决定(参考MySQL源代码/include/mysql_version.h头文件定义)
服务版本信息:该值为字符串,由 MYSQL_SERVER_VERSION 宏定义决定(参考MySQL源代码/include/mysql_version.h头文件定义)
服务器线程ID:服务器为当前连接所创建的线程ID。
挑战随机数:MySQL数据库用户认证采用的是挑战/应答的方式,服务器生成该挑战数并发送给客户端,由客户端进行处理并返回相应结果,然后服务器检查是否与预期的结果相同,从而完成用户认证的过程。
服务器权能标志:用于与客户端协商通讯方式,各标志位含义如下(参考MySQL源代码/include/mysql_com.h中的宏定义):
| 标志位名称 | 标志位 | 说明 |
|---|---|---|
| CLIENT_LONG_PASSWORD | 0x0001 | new more secure passwords |
| CLIENT_FOUND_ROWS | 0x0002 | Found instead of affected rows |
| CLIENT_LONG_FLAG | 0x0004 | Get all column flags |
| CLIENT_CONNECT_WITH_DB | 0x0008 | One can specify db on connect |
| CLIENT_NO_SCHEMA | 0x0010 | Do not allow database.table.column |
| CLIENT_COMPRESS | 0x0020 | Can use compression protocol |
| CLIENT_ODBC | 0x0040 | Odbc client |
| CLIENT_LOCAL_FILES | 0x0080 | Can use LOAD DATA LOCAL |
| CLIENT_IGNORE_SPACE | 0x0100 | Ignore spaces before '(' |
| CLIENT_PROTOCOL_41 | 0x0200 | New 4.1 protocol |
| CLIENT_INTERACTIVE | 0x0400 | This is an interactive client |
| CLIENT_SSL | 0x0800 | Switch to SSL after handshake |
| CLIENT_IGNORE_SIGPIPE | 0x1000 | IGNORE sigpipes |
| CLIENT_TRANSACTIONS | 0x2000 | Client knows about transactions |
| CLIENT_RESERVED | 0x4000 | Old flag for 4.1 protocol |
| CLIENT_SECURE_CONNECTION | 0x8000 | New 4.1 authentication |
| CLIENT_MULTI_STATEMENTS | 0x0001 0000 | Enable/disable multi-stmt support |
| CLIENT_MULTI_RESULTS | 0x0002 0000 | Enable/disable multi-results |
字符编码:标识服务器所使用的字符集。
服务器状态:状态值定义如下(参考MySQL源代码/include/mysql_com.h中的宏定义):
| 状态名称 | 状态值 |
|---|---|
| SERVER_STATUS_IN_TRANS | 0x0001 |
| SERVER_STATUS_AUTOCOMMIT | 0x0002 |
| SERVER_STATUS_CURSOR_EXISTS | 0x0040 |
| SERVER_STATUS_LAST_ROW_SENT | 0x0080 |
| SERVER_STATUS_DB_DROPPED | 0x0100 |
| SERVER_STATUS_NO_BACKSLASH_ESCAPES | 0x0200 |
| SERVER_STATUS_METADATA_CHANGED | 0x0400 |
4.1.2 登陆认证报文(客户端 -> 服务器)
MySQL 4.0 及之前的版本

MySQL 4.1 及之后的版本

客户端权能标志:用于与客户端协商通讯方式,标志位含义与握手初始化报文中的相同。客户端收到服务器发来的初始化报文后,会对服务器发送的权能标志进行修改,保留自身所支持的功能,然后将权能标返回给服务器,从而保证服务器与客户端通讯的兼容性。
最大消息长度:客户端发送请求报文时所支持的最大消息长度值。
字符编码:标识通讯过程中使用的字符编码,与服务器在认证初始化报文中发送的相同。
用户名:客户端登陆用户的用户名称。
挑战认证数据:客户端用户密码使用服务器发送的挑战随机数进行加密后,生成挑战认证数据,然后返回给服务器,用于对用户身份的认证。
数据库名称:当客户端的权能标志位 CLIENT_CONNECT_WITH_DB 被置位时,该字段必须出现。
4.2 客户端命令请求报文(客户端 -> 服务器)

命令:用于标识当前请求消息的类型,例如切换数据库(0x02)、查询命令(0x03)等。命令值的取值范围及说明如下表(参考MySQL源代码/include/mysql_com.h头文件中的定义):
| 类型值 | 命令 | 功能 | 关联函数 |
|---|---|---|---|
| 0x00 | COM_SLEEP | (内部线程状态) | (无) |
| 0x01 | COM_QUIT | 关闭连接 | mysql_close |
| 0x02 | COM_INIT_DB | 切换数据库 | mysql_select_db |
| 0x03 | COM_QUERY | SQL查询请求 | mysql_real_query |
| 0x04 | COM_FIELD_LIST | 获取数据表字段信息 | mysql_list_fields |
| 0x05 | COM_CREATE_DB | 创建数据库 | mysql_create_db |
| 0x06 | COM_DROP_DB | 删除数据库 | mysql_drop_db |
| 0x07 | COM_REFRESH | 清除缓存 | mysql_refresh |
| 0x08 | COM_SHUTDOWN | 停止服务器 | mysql_shutdown |
| 0x09 | COM_STATISTICS | 获取服务器统计信息 | mysql_stat |
| 0x0A | COM_PROCESS_INFO | 获取当前连接的列表 | mysql_list_processes |
| 0x0B | COM_CONNECT | (内部线程状态) | (无) |
| 0x0C | COM_PROCESS_KILL | 中断某个连接 | mysql_kill |
| 0x0D | COM_DEBUG | 保存服务器调试信息 | mysql_dump_debug_info |
| 0x0E | COM_PING | 测试连通性 | mysql_ping |
| 0x0F | COM_TIME | (内部线程状态) | (无) |
| 0x10 | COM_DELAYED_INSERT | (内部线程状态) | (无) |
| 0x11 | COM_CHANGE_USER | 重新登陆(不断连接) | mysql_change_user |
| 0x12 | COM_BINLOG_DUMP | 获取二进制日志信息 | (无) |
| 0x13 | COM_TABLE_DUMP | 获取数据表结构信息 | (无) |
| 0x14 | COM_CONNECT_OUT | (内部线程状态) | (无) |
| 0x15 | COM_REGISTER_SLAVE | 从服务器向主服务器进行注册 | (无) |
| 0x16 | COM_STMT_PREPARE | 预处理SQL语句 | mysql_stmt_prepare |
| 0x17 | COM_STMT_EXECUTE | 执行预处理语句 | mysql_stmt_execute |
| 0x18 | COM_STMT_SEND_LONG_DATA | 发送BLOB类型的数据 | mysql_stmt_send_long_data |
| 0x19 | COM_STMT_CLOSE | 销毁预处理语句 | mysql_stmt_close |
| 0x1A | COM_STMT_RESET | 清除预处理语句参数缓存 | mysql_stmt_reset |
| 0x1B | COM_SET_OPTION | 设置语句选项 | mysql_set_server_option |
| 0x1C | COM_STMT_FETCH | 获取预处理语句的执行结果 | mysql_stmt_fetch |
参数:内容是用户在MySQL客户端输入的命令(不包括每行命令结尾的";"分号)。另外这个字段的字符串不是以NULL字符结尾,而是通过消息头中的长度值计算而来。
例如:当我们在MySQL客户端中执行use hutaow;命令时(切换到hutaow数据库),发送的请求报文数据会是下面的样子:
0x02 0x68 0x75 0x74 0x61 0x6f 0x77
其中,0x02为请求类型值COM_INIT_DB,后面的0x68 0x75 0x74 0x61 0x6f 0x77为ASCII字符hutaow。
4.2.1 COM_QUIT 消息报文
功能:关闭当前连接(客户端退出),无参数。
4.2.2 COM_INIT_DB 消息报文
功能:切换数据库,对应的SQL语句为USE <database>。
| 字节 | 说明 |
|---|---|
| n | 数据库名称(字符串到达消息尾部时结束,无结束符) |
4.2.3 COM_QUERY 消息报文
功能:最常见的请求消息类型,当用户执行SQL语句时发送该消息。
| 字节 | 说明 |
|---|---|
| n | SQL语句(字符串到达消息尾部时结束,无结束符) |
4.2.4 COM_FIELD_LIST 消息报文
功能:查询某表的字段(列)信息,等同于SQL语句SHOW [FULL] FIELDS FROM ...。
| 字节 | 说明 |
|---|---|
| n | 表格名称(Null-Terminated String) |
| n | 字段(列)名称或通配符(可选) |
4.2.5 COM_CREATE_DB 消息报文
功能:创建数据库,该消息已过时,而被SQL语句CREATE DATABASE代替。
| 字节 | 说明 |
|---|---|
| n | 数据库名称(字符串到达消息尾部时结束,无结束符) |
4.2.6 COM_DROP_DB 消息报文
功能:删除数据库,该消息已过时,而被SQL语句DROP DATABASE代替。
| 字节 | 说明 |
|---|---|
| n | 数据库名称(字符串到达消息尾部时结束,无结束符) |
4.2.7 COM_REFRESH 消息报文
功能:清除缓存,等同于SQL语句FLUSH,或是执行mysqladmin flush-foo命令时发送该消息。
| 字节 | 说明 |
|---|---|
| 1 | 清除缓存选项(位图方式存储,各标志位含义如下) |
| 0x01: REFRESH_GRANT | |
| 0x02: REFRESH_LOG | |
| 0x04: REFRESH_TABLES | |
| 0x08: REFRESH_HOSTS | |
| 0x10: REFRESH_STATUS | |
| 0x20: REFRESH_THREADS | |
| 0x40: REFRESH_SLAVE | |
| 0x80: REFRESH_MASTER |
4.2.8 COM_SHUTDOWN 消息报文
功能:停止MySQL服务。执行mysqladmin shutdown命令时发送该消息。
| 字节 | 说明 |
|---|---|
| 1 | 停止服务选项 |
| 0x00: SHUTDOWN_DEFAULT | |
| 0x01: SHUTDOWN_WAIT_CONNECTIONS | |
| 0x02: SHUTDOWN_WAIT_TRANSACTIONS | |
| 0x08: SHUTDOWN_WAIT_UPDATES | |
| 0x10: SHUTDOWN_WAIT_ALL_BUFFERS | |
| 0x11: SHUTDOWN_WAIT_CRITICAL_BUFFERS | |
| 0xFE: KILL_QUERY | |
| 0xFF: KILL_CONNECTION |
4.2.9 COM_STATISTICS 消息报文
功能:查看MySQL服务的统计信息(例如运行时间、每秒查询次数等)。执行mysqladmin status命令时发送该消息,无参数。
4.2.10 COM_PROCESS_INFO 消息报文
功能:获取当前活动的线程(连接)列表。等同于SQL语句SHOW PROCESSLIST,或是执行mysqladmin processlist命令时发送该消息,无参数。
4.2.11 COM_PROCESS_KILL 消息报文
功能:要求服务器中断某个连接。等同于SQL语句KILL <id>。
| 字节 | 说明 |
|---|---|
| 4 | 连接ID号(小字节序) |
4.2.12 COM_DEBUG 消息报文
功能:要求服务器将调试信息保存下来,保存的信息多少依赖于编译选项设置(debug=no|yes|full)。执行mysqladmin debug命令时发送该消息,无参数。
4.2.13 COM_PING 消息报文
功能:该消息用来测试连通性,同时会将服务器的无效连接(超时)计数器清零。执行mysqladmin ping命令时发送该消息,无参数。
4.2.14 COM_CHANGE_USER 消息报文
功能:在不断连接的情况下重新登陆,该操作会销毁MySQL服务器端的会话上下文(包括临时表、会话变量等)。有些连接池用这种方法实现清除会话上下文。
| 字节 | 说明 |
|---|---|
| n | 用户名(字符串以NULL结尾) |
| n | 密码(挑战数) |
| MySQL 3.23 版本:Null-Terminated String(长度9字节) | |
| MySQL 4.1 版本:Length Coded String(长度1+21字节) | |
| n | 数据库名称(Null-Terminated String) |
| 2 | 字符编码 |
4.2.15 COM_BINLOG_DUMP 消息报文
功能:该消息是备份连接时由从服务器向主服务器发送的最后一个请求,主服务器收到后,会响应一系列的报文,每个报文都包含一个二进制日志事件。如果主服务器出现故障时,会发送一个EOF报文。
| 字节 | 说明 |
|---|---|
| 4 | 二进制日志数据的起始位置(小字节序) |
| 4 | 二进制日志数据标志位(目前未使用,永远为0x00) |
| 4 | 从服务器的服务器ID值(小字节序) |
| n | 二进制日志的文件名称(可选,默认值为主服务器上第一个有效的文件名) |
4.2.16 COM_TABLE_DUMP 消息报文
功能:将数据表从主服务器复制到从服务器中,执行SQL语句LOAD TABLE ... FROM MASTER时发送该消息。目前该消息已过时,不再使用。
| 字节 | 说明 |
|---|---|
| n | 数据库名称(Length Coded String) |
| n | 数据表名称(Length Coded String) |
4.2.17 COM_REGISTER_SLAVE 消息报文
功能:在从服务器report_host变量设置的情况下,当备份连接时向主服务器发送的注册消息。
| 字节 | 说明 |
|---|---|
| 4 | 从服务器ID值(小字节序) |
| n | 主服务器IP地址(Length Coded String) |
| n | 主服务器用户名(Length Coded String) |
| n | 主服务器密码(Length Coded String) |
| 2 | 主服务器端口号 |
| 4 | 安全备份级别(由MySQL服务器rpl_recovery_rank变量设置,暂时未使用) |
| 4 | 主服务器ID值(值恒为0x00) |
4.2.18 COM_PREPARE 消息报文
功能:预处理SQL语句,使用带有"?"占位符的SQL语句时发送该消息。
| 字节 | 说明 |
|---|---|
| n | 带有"?"占位符的SQL语句(字符串到达消息尾部时结束,无结束符) |
4.2.19 COM_EXECUTE 消息报文
功能:执行预处理语句。
| 字节 | 说明 |
|---|---|
| 4 | 预处理语句的ID值 |
| 1 | 标志位 |
| 0x00: CURSOR_TYPE_NO_CURSOR | |
| 0x01: CURSOR_TYPE_READ_ONLY | |
| 0x02: CURSOR_TYPE_FOR_UPDATE | |
| 0x04: CURSOR_TYPE_SCROLLABLE | |
| 4 | 保留(值恒为0x01) |
| 如果参数数量大于0 | |
| n | 空位图(Null-Bitmap,长度 = (参数数量 + 7) / 8 字节) |
| 1 | 参数分隔标志 |
| 如果参数分隔标志值为1 | |
| n | 每个参数的类型值(长度 = 参数数量 * 2 字节) |
| n | 每个参数的值 |
4.2.20 COM_LONG_DATA 消息报文
该消息报文有两种形式,一种用于发送二进制数据,另一种用于发送文本数据。
功能:用于发送二进制(BLOB)类型的数据(调用mysql_stmt_send_long_data函数)。
| 字节 | 说明 |
|---|---|
| 4 | 预处理语句的ID值(小字节序) |
| 2 | 参数序号(小字节序) |
| n | 数据负载(数据到达消息尾部时结束,无结束符) |
功能:用于发送超长字符串类型的数据(调用mysql_send_long_data函数)
| 字节 | 说明 |
|---|---|
| 4 | 预处理语句的ID值(小字节序) |
| 2 | 参数序号(小字节序) |
| 2 | 数据类型(未使用) |
| n | 数据负载(数据到达消息尾部时结束,无结束符) |
4.2.21 COM_CLOSE_STMT 消息报文
功能:销毁预处理语句。
| 字节 | 说明 |
|---|---|
| 4 | 预处理语句的ID值(小字节序) |
4.2.22 COM_RESET_STMT 消息报文
功能:将预处理语句的参数缓存清空。多数情况和COM_LONG_DATA一起使用。
| 字节 | 说明 |
|---|---|
| 4 | 预处理语句的ID值(小字节序) |
4.2.23 COM_SET_OPTION 消息报文
功能:设置语句选项,选项值为/include/mysql_com.h头文件中定义的enum_mysql_set_option枚举类型:
- MYSQL_OPTION_MULTI_STATEMENTS_ON
- MYSQL_OPTION_MULTI_STATEMENTS_OFF
| 字节 | 说明 |
|---|---|
| 2 | 选项值(小字节序) |
4.2.24 COM_FETCH_STMT 消息报文
功能:获取预处理语句的执行结果(一次可以获取多行数据)。
| 字节 | 说明 |
|---|---|
| 4 | 预处理语句的ID值(小字节序) |
| 4 | 数据的行数(小字节序) |
4.3 服务器响应报文(服务器 -> 客户端)
当客户端发起认证请求或命令请求后,服务器会返回相应的执行结果给客户端。客户端在收到响应报文后,需要首先检查第1个字节的值,来区分响应报文的类型。
| 响应报文类型 | 第1个字节取值范围 |
|---|---|
| OK 响应报文 | 0x00 |
| Error 响应报文 | 0xFF |
| Result Set 报文 | 0x01 - 0xFA |
| Field 报文 | 0x01 - 0xFA |
| Row Data 报文 | 0x01 - 0xFA |
| EOF 报文 | 0xFE |
注:响应报文的第1个字节在不同类型中含义不同,比如在OK报文中,该字节并没有实际意义,值恒为0x00;而在Result Set报文中,该字节又是长度编码的二进制数据结构(Length Coded Binary)中的第1字节。
4.3.1 OK 响应报文
客户端的命令执行正确时,服务器会返回OK响应报文。
MySQL 4.0 及之前的版本
| 字节 | 说明 |
|---|---|
| 1 | OK报文,值恒为0x00 |
| 1-9 | 受影响行数(Length Coded Binary) |
| 1-9 | 索引ID值(Length Coded Binary) |
| 2 | 服务器状态 |
| n | 服务器消息(字符串到达消息尾部时结束,无结束符) |
MySQL 4.1 及之后的版本
| 字节 | 说明 |
|---|---|
| 1 | OK报文,值恒为0x00 |
| 1-9 | 受影响行数(Length Coded Binary) |
| 1-9 | 索引ID值(Length Coded Binary) |
| 2 | 服务器状态 |
| 2 | 告警计数 |
| n | 服务器消息(字符串到达消息尾部时结束,无结束符,可选) |
受影响行数:当执行INSERT/UPDATE/DELETE语句时所影响的数据行数。
索引ID值:该值为AUTO_INCREMENT索引字段生成,如果没有索引字段,则为0x00。注意:当INSERT插入语句为多行数据时,该索引ID值为第一个插入的数据行索引值,而非最后一个。
服务器状态:客户端可以通过该值检查命令是否在事务处理中。
告警计数:告警发生的次数。
服务器消息:服务器返回给客户端的消息,一般为简单的描述性字符串,可选字段。
4.3.2 Error 响应报文
MySQL 4.0 及之前的版本
| 字节 | 说明 |
|---|---|
| 1 | Error报文,值恒为0xFF |
| 2 | 错误编号(小字节序) |
| n | 服务器消息 |
MySQL 4.1 及之后的版本
| 字节 | 说明 |
|---|---|
| 1 | Error报文,值恒为0xFF |
| 2 | 错误编号(小字节序) |
| 1 | 服务器状态标志,恒为'#'字符 |
| 5 | 服务器状态(5个字符) |
| n | 服务器消息 |
错误编号:错误编号值定义在源代码/include/mysqld_error.h头文件中。
服务器状态:服务器将错误编号通过mysql_errno_to_sqlstate函数转换为状态值,状态值由5字节的ASCII字符组成,定义在源代码/include/sql_state.h头文件中。
服务器消息:错误消息字符串到达消息尾时结束,长度可以由消息头中的长度值计算得出。消息长度为0-512字节。
4.3.3 Result Set 消息
当客户端发送查询请求后,在没有错误的情况下,服务器会返回结果集(Result Set)给客户端。
Result Set 消息分为五部分,结构如下:
| 结构 | 说明 |
|---|---|
| [Result Set Header] | 列数量 |
| [Field] | 列信息(多个) |
| [EOF] | 列结束 |
| [Row Data] | 行数据(多个) |
| [EOF] | 数据结束 |
4.3.4 Result Set Header 结构
| 字节 | 说明 |
|---|---|
| 1-9 | Field结构计数(Length Coded Binary) |
| 1-9 | 额外信息(Length Coded Binary) |
Field结构计数:用于标识Field结构的数量,取值范围0x00-0xFA。
额外信息:可选字段,一般情况下不应该出现。只有像SHOW COLUMNS这种语句的执行结果才会用到额外信息(标识表格的列数量)。
4.3.5 Field 结构
Field为数据表的列信息,在Result Set中,Field会连续出现多次,次数由Result Set Header结构中的IField结构计数值决定。
MySQL 4.0 及之前的版本
| 字节 | 说明 |
|---|---|
| n | 数据表名称(Length Coded String) |
| n | 列(字段)名称(Length Coded String) |
| 4 | 列(字段)长度(Length Coded String) |
| 2 | 列(字段)类型(Length Coded String) |
| 2 | 列(字段)标志(Length Coded String) |
| 1 | 整型值精度 |
| n | 默认值(Length Coded String) |
MySQL 4.1 及之后的版本
| 字节 | 说明 |
|---|---|
| n | 目录名称(Length Coded String) |
| n | 数据库名称(Length Coded String) |
| n | 数据表名称(Length Coded String) |
| n | 数据表原始名称(Length Coded String) |
| n | 列(字段)名称(Length Coded String) |
| 4 | 列(字段)原始名称(Length Coded String) |
| 1 | 填充值 |
| 2 | 字符编码 |
| 4 | 列(字段)长度 |
| 1 | 列(字段)类型 |
| 2 | 列(字段)标志 |
| 1 | 整型值精度 |
| 2 | 填充值(0x00) |
| n | 默认值(Length Coded String) |
目录名称:在4.1及之后的版本中,该字段值为"def"。
数据库名称:数据库名称标识。
数据表名称:数据表的别名(AS之后的名称)。
数据表原始名称:数据表的原始名称(AS之前的名称)。
列(字段)名称:列(字段)的别名(AS之后的名称)。
列(字段)原始名称:列(字段)的原始名称(AS之前的名称)。
字符编码:列(字段)的字符编码值。
列(字段)长度:列(字段)的长度值,真实长度可能小于该值,例如VARCHAR(2)类型的字段实际只能存储1个字符。
列(字段)类型:列(字段)的类型值,取值范围如下(参考源代码/include/mysql_com.h头文件中的enum_field_type枚举类型定义):
| 类型值 | 名称 |
|---|---|
| 0x00 | FIELD_TYPE_DECIMAL |
| 0x01 | FIELD_TYPE_TINY |
| 0x02 | FIELD_TYPE_SHORT |
| 0x03 | FIELD_TYPE_LONG |
| 0x04 | FIELD_TYPE_FLOAT |
| 0x05 | FIELD_TYPE_DOUBLE |
| 0x06 | FIELD_TYPE_NULL |
| 0x07 | FIELD_TYPE_TIMESTAMP |
| 0x08 | FIELD_TYPE_LONGLONG |
| 0x09 | FIELD_TYPE_INT24 |
| 0x0A | FIELD_TYPE_DATE |
| 0x0B | FIELD_TYPE_TIME |
| 0x0C | FIELD_TYPE_DATETIME |
| 0x0D | FIELD_TYPE_YEAR |
| 0x0E | FIELD_TYPE_NEWDATE |
| 0x0F | FIELD_TYPE_VARCHAR (new in MySQL 5.0) |
| 0x10 | FIELD_TYPE_BIT (new in MySQL 5.0) |
| 0xF6 | FIELD_TYPE_NEWDECIMAL (new in MYSQL 5.0) |
| 0xF7 | FIELD_TYPE_ENUM |
| 0xF8 | FIELD_TYPE_SET |
| 0xF9 | FIELD_TYPE_TINY_BLOB |
| 0xFA | FIELD_TYPE_MEDIUM_BLOB |
| 0xFB | FIELD_TYPE_LONG_BLOB |
| 0xFC | FIELD_TYPE_BLOB |
| 0xFD | FIELD_TYPE_VAR_STRING |
| 0xFE | FIELD_TYPE_STRING |
| 0xFF | FIELD_TYPE_GEOMETRY |
列(字段)标志:各标志位定义如下(参考源代码/include/mysql_com.h头文件中的宏定义):
| 标志位 | 名称 |
|---|---|
| 0x0001 | NOT_NULL_FLAG |
| 0x0002 | PRI_KEY_FLAG |
| 0x0004 | UNIQUE_KEY_FLAG |
| 0x0008 | MULTIPLE_KEY_FLAG |
| 0x0010 | BLOB_FLAG |
| 0x0020 | UNSIGNED_FLAG |
| 0x0040 | ZEROFILL_FLAG |
| 0x0080 | BINARY_FLAG |
| 0x0100 | ENUM_FLAG |
| 0x0200 | AUTO_INCREMENT_FLAG |
| 0x0400 | TIMESTAMP_FLAG |
| 0x0800 | SET_FLAG |
数值精度:该字段对DECIMAL和NUMERIC类型的数值字段有效,用于标识数值的精度(小数点位置)。
默认值:该字段用在数据表定义中,普通的查询结果中不会出现。
附:Field结构的相关处理函数:
- 客户端:
/client/client.c源文件中的unpack_fields函数 - 服务器:
/sql/sql_base.cc源文件中的send_fields函数
4.3.6 EOF 结构
EOF结构用于标识Field和Row Data的结束,在预处理语句中,EOF也被用来标识参数的结束。
MySQL 4.0 及之前的版本
| 字节 | 说明 |
|---|---|
| 1 | EOF值(0xFE) |
MySQL 4.1 及之后的版本
| 字节 | 说明 |
|---|---|
| 1 | EOF值(0xFE) |
| 2 | 告警计数 |
| 2 | 状态标志位 |
告警计数:服务器告警数量,在所有数据都发送给客户端后该值才有效。
状态标志位:包含类似SERVER_MORE_RESULTS_EXISTS这样的标志位。
注:由于EOF值与其它Result Set结构共用1字节,所以在收到报文后需要对EOF包的真实性进行校验,校验条件为:
- 第1字节值为0xFE
- 包长度小于9字节
附:EOF结构的相关处理函数:
- 服务器:
protocol.cc源文件中的send_eof函数
4.3.7 Row Data 结构
在Result Set消息中,会包含多个Row Data结构,每个Row Data结构又包含多个字段值,这些字段值组成一行数据。
| 字节 | 说明 |
|---|---|
| n | 字段值(Length Coded String) |
| ... | (一行数据中包含多个字段值) |
字段值:行数据中的字段值,字符串形式。
附:Row Data结构的相关处理函数:
- 客户端:
/client/client.c源文件中的read_rows函数
4.3.8 Row Data 结构(二进制数据)
该结构用于传输二进制的字段值,既可以是服务器返回的结果,也可以是由客户端发送的(当执行预处理语句时,客户端使用Result Set消息来发送参数及数据)。
| 字节 | 说明 |
|---|---|
| 1 | 结构头(0x00) |
| (列数量 + 7 + 2) / 8 | 空位图 |
| n | 字段值 |
| ... | (一行数据中包含多个字段值) |
空位图:前2个比特位被保留,值分别为0和1,以保证不会和OK、Error包的首字节冲突。在MySQL 5.0及之后的版本中,这2个比特位的值都为0。
字段值:行数据中的字段值,二进制形式。
4.3.9 PREPARE_OK 响应报文(Prepared Statement)
用于响应客户端发起的预处理语句报文,组成结构如下:
| 结构 | 说明 |
|---|---|
| [PREPARE_OK] | PREPARE_OK结构 |
| 如果参数数量大于0 | |
| [Field] | 与Result Set消息结构相同 |
| [EOF] | |
| 如果列数大于0 | |
| [Field] | 与Result Set消息结构相同 |
| [EOF] |
其中 PREPARD_OK 的结构如下:
| 字节 | 说明 |
|---|---|
| 1 | OK报文,值为0x00 |
| 4 | 预处理语句ID值 |
| 2 | 列数量 |
| 2 | 参数数量 |
| 1 | 填充值(0x00) |
| 2 | 告警计数 |
4.3.10 Parameter 响应报文(Prepared Statement)
预处理语句的值与参数正确对应后,服务器会返回 Parameter 报文。
| 字节 | 说明 |
|---|---|
| 2 | 类型 |
| 2 | 标志 |
| 1 | 数值精度 |
| 4 | 字段长度 |
类型:与 Field 结构中的字段类型相同。
标志:与 Field 结构中的字段标志相同。
数值精度:与 Field 结构中的数值精度相同。
字段长度:与 Field 结构中的字段长度相同。
5 参考资料
MySQL协议分析的更多相关文章
- MySQL协议分析2
MySQL协议分析 议程 协议头 协议类型 网络协议相关函数 NET缓冲 VIO缓冲 MySQL API 协议头 ● 数据变成在网络里传输的数据,需要额外的在头部添加4 个字节的包头. . packe ...
- MySQL协议分析(2)
MySQL协议分析(2) 此阶段是在压缩传输无加密条件下进行的协议分析 思路 结合Oracle官网的说明和自己用wireshark加python进行数据包分析 步骤 客户端与服务器端是否压缩的协商阶段 ...
- MySQL协议分析(1)
MySQL协议分析 此阶段的协议分析是在未压缩未加密情况下的协议分析 思路: 结合Oracle官网和自己用wireshark抓的网络数据包进行协议分析 官网说明 mysql包共分为4段,格式如下: 第 ...
- mixer: mysql协议分析
综述 要实现一个mysql proxy,首先需要做的就是理解并实现mysql通讯协议.这样才能通过proxy架起client到server之间的桥梁. mixer的mysql协议实现主要参考mysql ...
- mysql 协议分析
MYSQL Binlog协议分析 此处不讨论建立连接,验证和handshake的交互协议 Binlog协议 一个MYSQL 通信包由包头包体组成 包体根据具体的交互协议有自身的组成结构, 在binlo ...
- mysql协议分析2---认证包
主人看到navicat和mysql在那嘻嘻哈哈,眉来眼去的,好不快乐,忽然也想自己写个程序,直接去访问Mysql,虽然现在已经有很多现成的中间件可以直接拿来用了,程序只要负责写sql语句就行了,但是主 ...
- mysql协议分析1---报文的格式和基本类型
navicat 和 mysql 是一对好基友,每天都有非常频繁的交流,主人在navicat上写下每条sql语句,轻轻的点了下执行按钮,navicat就飞快的把主人的指令传送到mysql那里,mysql ...
- mysql协议简析
前言 如果要在命令行中连接mysql,最常用的便是 mysql -u root -p 这样指定用户名和密码 当然还可以使用远程连接 mysql -h 127.0.0.1 -u root -p 还有一种 ...
- Memcache的使用和协议分析详解
Memcache的使用和协议分析详解 作者:heiyeluren博客:http://blog.csdn.NET/heiyeshuwu时间:2006-11-12关键字:PHP Memcache Linu ...
随机推荐
- 告别山寨数据线:USB Type-C加密认证出炉
从去年苹果发布的MacBook首次采用USB Type-C接口开始,这一标准逐渐成为主流,许多旗舰手机慢慢地采用了这种接口.今日,非盈利机构USB开发者论坛(USB-IF)宣布了USB Type-C认 ...
- Two-Phase Locking
两阶段封锁(Two-Phase Locking) 两段锁协议的内容 1. 在对任何数据进行读.写操作之前,事务首先要获得对该数据的封锁 2. 在释放一个封锁之后,事务不再获得任何其他封锁. “两段”锁 ...
- BZOJ_1619_[Usaco2008_Nov]_Guarding_the_Farm_保卫牧场_(模拟+bfs)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1619 给出一张图每个点的高度,在一个点上安排守卫可以监视周围所有不高于于当前点的点.也就是类似 ...
- ☀【window.self / window.parent / window.top】
Js中的window.parent ,window.top,window.self 详解 √http://blog.csdn.net/zdwzzu2006/article/details/604763 ...
- apache开源项目--lucence
Lucene 是apache软件基金会一个开放源代码的全文检索引擎工具包,是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎.Lucene的目的是为软件开发人员提供一个简单易用 ...
- 处理MVC中默认的Json方法返回时间的问题
利用 Json方法返回 数据时,如果有时间格式,会变成 "\/Date(1369419656217)\/" 这个样子,问了同事找到个解决方法 using Newtonsoft.Js ...
- 基于DDD的现代ASP.NET开发框架--ABP系列之2、ABP入门教程
基于DDD的现代ASP.NET开发框架--ABP系列之2.ABP入门教程 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boi ...
- nyoj 96 一个水题目
虽然很简单,发现自己用内存太高了了,算了,我就是这水平了. 描述 已知w是一个大于10但不大于1000000的无符号整数,若w是n(n≥2)位的整数,则求出w的后n-1位的数. 输入 第一行为M,表示 ...
- ACM2030_机内码
/* 汉字统计 问题说明 统计给定文本文件中汉字的个数. 输入 输入文件首先包含一个整数Ñ,表示测试实例的个数,然后是Ñ段文本. 产量 对于每一段文本,输出其中的汉字的个数,每个测试实例的输出 ...
- 【原创】Mac上编译Hadoop1.0.3出现的一些问题
create-native-configure: [exec] configure.ac:47: error: possibly undefined macro: AC_PROG_LIBTOOL [e ...