分类: Mysql/postgreSQL
2013-06-06 09:12:57
目的
基于《MySQL数据结构分析--protocol》对MySQL中Server端的协议格式和网络封装的详细分析和说明,本文对MySQL客户端命令格式和网络结构封装进行分析,深入理解MySQL服务器和客户端之间的通信协议。
数据结构
MySQL客户端涉及的数据结构较多,其中主要包括MYSQL客户端数据结构、MYSQL_RES客户端结果数据结构、MYSQL_BIND客户端绑定信 息数据结构、MYSQL_STMT客户端SQL语句数据结构、MYSQL_FIELD客户端字段信息数据结构、MYSQL_ROW客户端数据每行数据结 构、MYSQL_ROWS客户端数据行结果集数据结构(MYSQL_ROW的链式结构)、MYSQL_DATA客户端数据内容数据结构。
这些数据结果,在客户端发送SQL命令或者接收执行结果时,分别用于绑定和存储输入参数和输出结果,是客户端和服务器端交互时重要的数据结构。
数据结构的定义参考源码文件include\mysql.h,其中定义了所有这些数据结构,以及相关的辅助数据结构。
格式
MySQL客户端的格式主要包括网络传输格式和命令格式两种,这些内容在源码文件sql-common\client.c中。以下分别对这两种格式进行分析。
MySQL客户端网络传输格式:
MySQL客户端网络传输结构的封装主要分为两种,一种是简单命令网络传输结构、一种是高级命令网络传输结构。简单命令传输仅仅传输命令类型和命令参数, 而高级命令传输需要传输命令的类型、命令头信息、以及命令参数。网络传输通过调用cli_advanced_command()函数进行发送,通过输入的 header和header_len参数区分两种封装格式,分别调用net_write_command()函数进行实际的packet写处理。
简单命令网络传输结构具体如下所示:
图1 简单命令网络传输结构
高级命令网络传输结构具体如下所示:
图2 高级命令网络传输结构
MySQL客户端命令格式:
MySQL客户端命令按照功能分为两种:一种是解析服务器端的协议,一种是封装客户端命令发送至服务器端。其中解析服务器端的协议主要根据服务器端的协议 格式,进行解析出对应字段的信息,并存储在客户端相应的数据结构中。由于客户端解析服务器端的协议是服务器端协议封装的逆操作,因此不再赘述。
由于大多数客户端发送的信息是命令,因此大多直接调用net_write_command()函数进行网络写处理,而没有真正的packet封装,故不再赘述。因此,以下内容对客户端复杂packet封装进行分析。
change_user_packet封装格式
在send_change_user_packet()函数中,packet的内容不是简单的命令和简单的参数,而是根据客户端的版本不同和数据长度的不 同,对packet数据进行封装。根据客户端版本的和数据长度的不同,有以下四种packet的封装格式:
客户端协议版本4.1:
图3数据长度为0的封装格式
图4数据长度不为0的封装格式
各个字段的含义根据字段名可知,不再赘述。数据长度为0时,数据存储长度0,而数据长度不为0时,存储相应的数据内容。此外如果客户端支持plugin,那么封装plugin_name进行发送。
客户端协议之前版本:
图5 数据长度为0的封装格式
图6 数据长度不为0的封装格式
与客户端协议4.1封装结构不同的是chaset_num字段,这个字段在4.1协议中存储字符集类型。除此之外,与客户端协议4.1一致。
client_reply_packet封装格式
在send_client_reply_packet()函数中,MySQL对回复packet进行封装。根据客户端协议的不同,分为以下两种格式。具体格式如下所示:
客户端协议版本4.1:
图7 客户端协议版本4.1的封装格式
从封装格式可知,client_flag用于存储客户端的标志位,max_packet_size用于存储packet包的最大长 度,chaset_num用于存储字符集类型,之后23个字节预留,user_name表示用户名,data_len和data分别用于表示密码的长度和 密码,db表示数据库名,plugin_name表示客户端插件名。
客户端协议之前版本:
图8 客户端协议之前版本封装格式
与客户端协议版本4.1不同的是,client_flag标志位占2个字节,max_packet_size占3个字节,而密码信息通过固定占用9个字节存储。
结论
通过MySQL客户端传输格式和命令格式的分析,结合《MySQL数据结构分析--protocol》中服务器端的协议分析,对MySQL客户端和服务器端的通信协议有深入的理解。