MySQL之——协议分析(上篇)

目录

  • 目录
  • 1 交互过程
    • 1.1 握手认证阶段
    • 1.2 命令执行阶段
  • 2 基本类型
    • 2.1 整型值
    • 2.2 字符串(以NULL结尾)(Null-Terminated String)
    • 2.3 二进制数据(长度编码)(Length Coded Binary)
    • 2.4 字符串(长度编码)(Length Coded String)
  • 3 报文结构
    • 3.1 消息头
      • 3.1.1 报文长度
      • 3.1.2 序号
    • 3.2 消息体
  • 4 报文类型
    • 4.1 登陆认证交互报文
      • 4.1.1 握手初始化报文(服务器 -> 客户端)
      • 4.1.2 登陆认证报文(客户端 -> 服务器)
    • 4.2 客户端命令请求报文(客户端 -> 服务器)
      • 4.2.1 COM_QUIT 消息报文
      • 4.2.2 COM_INIT_DB 消息报文
      • 4.2.3 COM_QUERY 消息报文
      • 4.2.4 COM_FIELD_LIST 消息报文
      • 4.2.5 COM_CREATE_DB 消息报文
      • 4.2.6 COM_DROP_DB 消息报文
      • 4.2.7 COM_REFRESH 消息报文
      • 4.2.8 COM_SHUTDOWN 消息报文
      • 4.2.9 COM_STATISTICS 消息报文
      • 4.2.10 COM_PROCESS_INFO 消息报文
      • 4.2.11 COM_PROCESS_KILL 消息报文
      • 4.2.12 COM_DEBUG 消息报文
      • 4.2.13 COM_PING 消息报文
      • 4.2.14 COM_CHANGE_USER 消息报文
      • 4.2.15 COM_BINLOG_DUMP 消息报文
      • 4.2.16 COM_TABLE_DUMP 消息报文
      • 4.2.17 COM_REGISTER_SLAVE 消息报文
      • 4.2.18 COM_PREPARE 消息报文
      • 4.2.19 COM_EXECUTE 消息报文
      • 4.2.20 COM_LONG_DATA 消息报文
      • 4.2.21 COM_CLOSE_STMT 消息报文
      • 4.2.22 COM_RESET_STMT 消息报文
      • 4.2.23 COM_SET_OPTION 消息报文
      • 4.2.24 COM_FETCH_STMT 消息报文
    • 4.3 服务器响应报文(服务器 -> 客户端)
      • 4.3.1 OK 响应报文
      • 4.3.2 Error 响应报文
      • 4.3.3 Result Set 消息
      • 4.3.4 Result Set Header 结构
      • 4.3.5 Field 结构
      • 4.3.6 EOF 结构
      • 4.3.7 Row Data 结构
      • 4.3.8 Row Data 结构(二进制数据)
      • 4.3.9 PREPARE_OK 响应报文(Prepared Statement)
      • 4.3.10 Parameter 响应报文(Prepared Statement)
  • 5 参考资料

1 交互过程

MySQL客户端与服务器的交互主要分为两个阶段:握手认证阶段和命令执行阶段。

1.1 握手认证阶段

握手认证阶段为客户端与服务器建立连接后进行,交互过程如下:

  • 服务器 -> 客户端:握手初始化消息
  • 客户端 -> 服务器:登陆认证消息
  • 服务器 -> 客户端:认证结果消息

1.2 命令执行阶段

客户端认证成功后,会进入命令执行阶段,交互过程如下:

  • 客户端 -> 服务器:执行命令消息
  • 服务器 -> 客户端:命令执行结果

MySQL客户端与服务器的完整交互过程如下

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-2500第一个字节值即为数据的真实长度
2510空数据,数据的真实长度为零
2522后续额外2个字节标识了数据的真实长度
2533后续额外3个字节标识了数据的真实长度
2548后续额外8个字节标识了数据的真实长度

2.4 字符串(长度编码)(Length Coded String)

字符串长度不固定,无'NULL'(0x00)结束符,编码方式与上面的 Length Coded Binary 相同。

3 报文结构

报文分为消息头和消息体两部分,其中消息头占用固定的4个字节,消息体长度由消息头中的长度字段决定,报文结构如下:

MySQL报文结构

3.1 消息头

3.1.1 报文长度

用于标记当前请求消息的实际数据长度值,以字节为单位,占用3个字节,最大值为 0xFFFFFF,即接近 16 MB 大小(比16MB少1个字节)。

3.1.2 序号

在一次完整的请求/响应交互过程中,用于保证消息顺序的正确,每次客户端发起请求时,序号值都会从0开始计算。

3.2 消息体

消息体用于存放请求的内容及响应的数据,长度由消息头中的长度值决定。

4 报文类型

4.1 登陆认证交互报文

4.1.1 握手初始化报文(服务器 -> 客户端)

MySQL握手初始化报文

服务协议版本号:该值由 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_PASSWORD0x0001new more secure passwords
CLIENT_FOUND_ROWS0x0002Found instead of affected rows
CLIENT_LONG_FLAG0x0004Get all column flags
CLIENT_CONNECT_WITH_DB0x0008One can specify db on connect
CLIENT_NO_SCHEMA0x0010Do not allow database.table.column
CLIENT_COMPRESS0x0020Can use compression protocol
CLIENT_ODBC0x0040Odbc client
CLIENT_LOCAL_FILES0x0080Can use LOAD DATA LOCAL
CLIENT_IGNORE_SPACE0x0100Ignore spaces before '('
CLIENT_PROTOCOL_410x0200New 4.1 protocol
CLIENT_INTERACTIVE0x0400This is an interactive client
CLIENT_SSL0x0800Switch to SSL after handshake
CLIENT_IGNORE_SIGPIPE0x1000IGNORE sigpipes
CLIENT_TRANSACTIONS0x2000Client knows about transactions
CLIENT_RESERVED0x4000Old flag for 4.1 protocol
CLIENT_SECURE_CONNECTION0x8000New 4.1 authentication
CLIENT_MULTI_STATEMENTS0x0001 0000Enable/disable multi-stmt support
CLIENT_MULTI_RESULTS0x0002 0000Enable/disable multi-results

字符编码:标识服务器所使用的字符集。

服务器状态:状态值定义如下(参考MySQL源代码/include/mysql_com.h中的宏定义):

状态名称状态值
SERVER_STATUS_IN_TRANS0x0001
SERVER_STATUS_AUTOCOMMIT0x0002
SERVER_STATUS_CURSOR_EXISTS0x0040
SERVER_STATUS_LAST_ROW_SENT0x0080
SERVER_STATUS_DB_DROPPED0x0100
SERVER_STATUS_NO_BACKSLASH_ESCAPES0x0200
SERVER_STATUS_METADATA_CHANGED0x0400

4.1.2 登陆认证报文(客户端 -> 服务器)

MySQL 4.0 及之前的版本

MySQL登陆认证报文(4.0及之前的版本)

MySQL 4.1 及之后的版本

MySQL登陆认证报文(4.1及之后的版本)

客户端权能标志:用于与客户端协商通讯方式,标志位含义与握手初始化报文中的相同。客户端收到服务器发来的初始化报文后,会对服务器发送的权能标志进行修改,保留自身所支持的功能,然后将权能标返回给服务器,从而保证服务器与客户端通讯的兼容性。

最大消息长度:客户端发送请求报文时所支持的最大消息长度值。

字符编码:标识通讯过程中使用的字符编码,与服务器在认证初始化报文中发送的相同。

用户名:客户端登陆用户的用户名称。

挑战认证数据:客户端用户密码使用服务器发送的挑战随机数进行加密后,生成挑战认证数据,然后返回给服务器,用于对用户身份的认证。

数据库名称:当客户端的权能标志位 CLIENT_CONNECT_WITH_DB 被置位时,该字段必须出现。

4.2 客户端命令请求报文(客户端 -> 服务器)

MySQL客户端命令请求报文

命令:用于标识当前请求消息的类型,例如切换数据库(0x02)、查询命令(0x03)等。命令值的取值范围及说明如下表(参考MySQL源代码/include/mysql_com.h头文件中的定义):

类型值命令功能关联函数
0x00COM_SLEEP(内部线程状态)(无)
0x01COM_QUIT关闭连接mysql_close
0x02COM_INIT_DB切换数据库mysql_select_db
0x03COM_QUERYSQL查询请求mysql_real_query
0x04COM_FIELD_LIST获取数据表字段信息mysql_list_fields
0x05COM_CREATE_DB创建数据库mysql_create_db
0x06COM_DROP_DB删除数据库mysql_drop_db
0x07COM_REFRESH清除缓存mysql_refresh
0x08COM_SHUTDOWN停止服务器mysql_shutdown
0x09COM_STATISTICS获取服务器统计信息mysql_stat
0x0ACOM_PROCESS_INFO获取当前连接的列表mysql_list_processes
0x0BCOM_CONNECT(内部线程状态)(无)
0x0CCOM_PROCESS_KILL中断某个连接mysql_kill
0x0DCOM_DEBUG保存服务器调试信息mysql_dump_debug_info
0x0ECOM_PING测试连通性mysql_ping
0x0FCOM_TIME(内部线程状态)(无)
0x10COM_DELAYED_INSERT(内部线程状态)(无)
0x11COM_CHANGE_USER重新登陆(不断连接)mysql_change_user
0x12COM_BINLOG_DUMP获取二进制日志信息(无)
0x13COM_TABLE_DUMP获取数据表结构信息(无)
0x14COM_CONNECT_OUT(内部线程状态)(无)
0x15COM_REGISTER_SLAVE从服务器向主服务器进行注册(无)
0x16COM_STMT_PREPARE预处理SQL语句mysql_stmt_prepare
0x17COM_STMT_EXECUTE执行预处理语句mysql_stmt_execute
0x18COM_STMT_SEND_LONG_DATA发送BLOB类型的数据mysql_stmt_send_long_data
0x19COM_STMT_CLOSE销毁预处理语句mysql_stmt_close
0x1ACOM_STMT_RESET清除预处理语句参数缓存mysql_stmt_reset
0x1BCOM_SET_OPTION设置语句选项mysql_set_server_option
0x1CCOM_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语句时发送该消息。

字节说明
nSQL语句(字符串到达消息尾部时结束,无结束符)

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 及之前的版本

字节说明
1OK报文,值恒为0x00
1-9受影响行数(Length Coded Binary)
1-9索引ID值(Length Coded Binary)
2服务器状态
n服务器消息(字符串到达消息尾部时结束,无结束符)

MySQL 4.1 及之后的版本

字节说明
1OK报文,值恒为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 及之前的版本

字节说明
1Error报文,值恒为0xFF
2错误编号(小字节序)
n服务器消息

MySQL 4.1 及之后的版本

字节说明
1Error报文,值恒为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-9Field结构计数(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枚举类型定义):

类型值名称
0x00FIELD_TYPE_DECIMAL
0x01FIELD_TYPE_TINY
0x02FIELD_TYPE_SHORT
0x03FIELD_TYPE_LONG
0x04FIELD_TYPE_FLOAT
0x05FIELD_TYPE_DOUBLE
0x06FIELD_TYPE_NULL
0x07FIELD_TYPE_TIMESTAMP
0x08FIELD_TYPE_LONGLONG
0x09FIELD_TYPE_INT24
0x0AFIELD_TYPE_DATE
0x0BFIELD_TYPE_TIME
0x0CFIELD_TYPE_DATETIME
0x0DFIELD_TYPE_YEAR
0x0EFIELD_TYPE_NEWDATE
0x0FFIELD_TYPE_VARCHAR (new in MySQL 5.0)
0x10FIELD_TYPE_BIT (new in MySQL 5.0)
0xF6FIELD_TYPE_NEWDECIMAL (new in MYSQL 5.0)
0xF7FIELD_TYPE_ENUM
0xF8FIELD_TYPE_SET
0xF9FIELD_TYPE_TINY_BLOB
0xFAFIELD_TYPE_MEDIUM_BLOB
0xFBFIELD_TYPE_LONG_BLOB
0xFCFIELD_TYPE_BLOB
0xFDFIELD_TYPE_VAR_STRING
0xFEFIELD_TYPE_STRING
0xFFFIELD_TYPE_GEOMETRY

列(字段)标志:各标志位定义如下(参考源代码/include/mysql_com.h头文件中的宏定义):

标志位名称
0x0001NOT_NULL_FLAG
0x0002PRI_KEY_FLAG
0x0004UNIQUE_KEY_FLAG
0x0008MULTIPLE_KEY_FLAG
0x0010BLOB_FLAG
0x0020UNSIGNED_FLAG
0x0040ZEROFILL_FLAG
0x0080BINARY_FLAG
0x0100ENUM_FLAG
0x0200AUTO_INCREMENT_FLAG
0x0400TIMESTAMP_FLAG
0x0800SET_FLAG

数值精度:该字段对DECIMALNUMERIC类型的数值字段有效,用于标识数值的精度(小数点位置)。

默认值:该字段用在数据表定义中,普通的查询结果中不会出现。

:Field结构的相关处理函数:

  • 客户端:/client/client.c源文件中的unpack_fields函数
  • 服务器:/sql/sql_base.cc源文件中的send_fields函数

4.3.6 EOF 结构

EOF结构用于标识Field和Row Data的结束,在预处理语句中,EOF也被用来标识参数的结束。

MySQL 4.0 及之前的版本

字节说明
1EOF值(0xFE)

MySQL 4.1 及之后的版本

字节说明
1EOF值(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 的结构如下:

字节说明
1OK报文,值为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 Internals Manual: MySQL Client/Server Protocol》

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页