MySql协议分析

Mysql协议分析

实验环境:

客户端(10.88.42.61)环境:MAC OSX+mysql客户端+wireshark

服务器环境(10.88.42.57):Linux6+mysql5.6

实验方案:使用抓包工具Wireshark,对mysql客户端从连接mysql服务器到执行各种命令的过程中进行抓包,并配和资料进行分析。以下是一些资料分析:

1.     交互过程

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

1.1   握手认证阶段

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

服务器->客户端:握手初始化消息

客户端->服务器:登陆认证消息

服务器->客户端:认证结果消息

1.2   命令执行阶段

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

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

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

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


 

开始实验:

1.     登陆认证交互报文

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

workbench连接到服务的过程中抓到的mysql协议包如下所示


通过Wireshark的分析很容易看出mysql协议是封装在TCP协议中,结合如下所示的其报文结构:


服务协议版本号:该值由 PROTOCOL_VERSION 宏定义决定(参考MySQL源代码/include/mysql_version.h头文件定义),抓包显示协议版本号为10

服务版本信息:该值为字符串,由 MYSQL_SERVER_VERSION 宏定义决定(参考MySQL源代码/include/mysql_version.h头文件定义),抓包显示mysql服务器版本为5.6.22

服务器线程ID:服务器为当前连接所创建的线程ID。因为客户端创连接到服务器,服务器分配给单独的进程,抓包显示进程号为5,可通过登陆键入show process list验证

mysql> show processlist;

+----+------+-------------------+---------+---------+------+-------+------------------+

| Id | User | Host              | db      | Command | Time | State | Info             |

+----+------+-------------------+---------+---------+------+-------+------------------+

|  5 | lgs  | 10.88.42.61:56326 | myworld | Sleep   | 2736 |       | NULL             |

|  6 | lgs  | 10.88.42.61:56327 | myworld | Sleep   | 2736 |       | NULL             |

|  7 | root | localhost         | NULL    | Query   |    0 | init  | show processlist |

+----+------+-------------------+---------+---------+------+-------+------------------+

挑战随机数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 登陆认证报文(客户端 -> 服务器)

当客户端接收到服务端的初始化报文,那么客户端会接着向服务器发送登陆认证报文,抓去的报文如下,很明显可以看到用户名和加密后的密码:


下面是摘自官网的详细报文格式


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

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

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

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


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

数据库名称:当客户端的权能标志位 CLIENT_CONNECT_WITH_DB 被置位时,该字段必须出现,如客户端权能显示连接数据库这个参数未被设置,因此抓取到的包中未能显示信息。

4.2. 客户端命令请求报文

要知道数据库作为作为一个业务核心的系统的软件,存储大量的数据,所有客户端会频繁向服务器发送命令请求报文,另外命令请求报文并没有其他的mysql报文那么复杂,消息体如下:


命令:用于标识当前请求消息的类型,例如切换数据库(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 test;命令时(切换到test数据库),这里要注意的是虽然用户键入的只有use test这一条命令,但是客户端发送的请求却是多条的为了说明命令类型特地挑出切换数据库命令和获取表的列信息,发送的数据库切换请求报文数据会是下面的样子:


 

其中,0x02为请求类型值COM_INIT_DB,后面的为ASCII字符test

另外客户自动请求数据库中表的列信息,请求报文是这样的:


其中,0x04就是获取数据表字段命令,后面的ASCII就是指对应的表了。

下面是能搜索到的命令信息:

4.2.1 COM_QUIT 消息报文

功能:关闭当前连接(客户端退出),无参数。

4.2.2 COM_INIT_DB 消息报文

功能:切换数据库,对应的SQL语句为USE

字节

   说明

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

字节

    说明

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字节。

下面实验的表结构是这样的:

mysql> desc student;

+-------+-------------+------+-----+---------+-------+

| Field | Type        | Null | Key | Default | Extra |

+-------+-------------+------+-----+---------+-------+

| id    | int(11)     | NO   | PRI | NULL    |       |

| name  | varchar(10) | YES  |     | NULL    |       |

+-------+-------------+------+-----+---------+-------+

2 rows in set (0.00 sec)

 

4.3.1 OK 响应报文

客户端的命令执行正确时,服务器会返回OK响应报文。

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值为第一个插入的数据行索引值,而非最后一个。

服务器状态:客户端可以通过该值检查命令是否在事务处理中。

告警计数:告警发生的次数。

服务器消息:服务器返回给客户端的消息,一般为简单的描述性字符串,可选字段。

现在往实验表中插入数据:

mysql> insert into student values(3,'kate');

Query OK, 1 row affected (0.00 sec)

返回的报文过滤出OK

包长(07 00)+包号(00 01)+报文类型(00  OK包)+影响行数(01)+索引id值(00 自增长索引未设置)+服务器状态(02 00)+无警告+服务器状态(00 00)+无计数+消息未选
具体如下:

 
4.3.2 Error 响应报文

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字节。

实验中插入上一条一样的数据,造成违反主键唯一性约束的错误。

抓取到包如下:


详细看第五个字节为ff也证明来这是一个错误包,详细的报文对照分析如下:


4.3.3 Result Set 消息(重要)

当客户端发送查询请求后,在没有错误的情况下,服务器会返回结果集(Result Set)给客户端。

Result Set 消息分为五部分,结构如下:

结构

说明

[Result Set Header]

列数量

[Field]

列信息(多个)

[EOF]

列结束

[Row Data]

行数据(多个)

[EOF]

数据结束

实验中执行如下进行抓包分析:

mysql> select * from student;

+----+------+

| id | name |

+----+------+

|  1 | jack |

|  2 | tom  |

|  3 | kate |

+----+------+

3 rows in set (0.00 sec)
抓到的包如下显示

显示有八个报文,由上以及student表结构分析,是1个结果集头包+2个列信息包+1个列结束包+3个行数据包+1个数据结束包
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.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



 


对应进制码的结尾可以fd对应FIELD_TYPE_VAR_STTING,其他的不做赘述,大家对号入座。

列(字段)标志:各标志位定义如下(参考源代码/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

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

抓包的进制码显示的列标志,实际上说明的是列的属性

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

Field结构的相关处理函数:

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

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

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函数

列信息的EOF



行数据的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个比特位被保留,值分别为01,以保证不会和OKError包的首字节冲突。在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 结构中的字段长度相同。


报文长度(07 00 00)+报文序列号(05)+报文类型(01


5 参考资料

MySQL Internals Manual: MySQL Client/Server Protocol

 


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/28944233/viewspace-1665982/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/28944233/viewspace-1665982/

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值