Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1145775
  • 博文数量: 646
  • 博客积分: 288
  • 博客等级: 二等列兵
  • 技术积分: 5375
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-08 14:33
个人简介

为了技术,我不会停下学习的脚步,我相信我还能走二十年。

文章分类

全部博文(646)

文章存档

2014年(8)

2013年(134)

2012年(504)

分类: Mysql/postgreSQL

2013-02-25 09:08:31

 

目的

       MySQL数据结构Protocol及相关处理方法,是MySQL服务器端遵循的协议规范。本文通过解析MySQL服务器端的协议,分析各种协议的格式,以便于更清晰的了解协议规则。

数据结构

       Protocol数据结构定义在MySQL的源码sql/protocol.h中,Protocolclass类型,派生了Protocol_textProtocol_binary两个子类,分别用于处理字符类数据和二进制数据的存储。Protocol类的关系图如下所示:

1 Protocol类关系

       Protocol类中主要的分为三类:基本参数、数据存储、数据发送。其中基本参数主要包括thdTHD数据结构,主要用于存储当前线程session的一些参数;packet是数据包字段;此外还有字段相关的变量,如field_count字段数、field_pos字段位置、field_types字段类型等。数据存储相关处理方法主要是用于处理和存储不同字段类型的数据,这些方法对不同的数据类型,可以在派生类里面进行重写。数据发送主要包括发送执行状态和发送数据等处理方法,其中在数据发送阶段是协议格式的封装过程,并且在发送数据时调用数据存储的相关处理方法,根据数据字段的类型,对数据进行封装发送。

协议格式

       协议格式部分主要从发送阶段数据格式的封装角度来诠释MySQL数据传输协议。以下将对所有的数据传输传输格式进行分析,由于客户端协议版本的问题,有些数据格式也有所不同。

error信息格式

       error信息是执行状态的一种,发送error信息,根据客户端不同的协议版本,有以下两种格式。

客户端协议4.1error信息格式:

2 客户端4.1协议error信息格式

       errnoMySQL对应的错误号,2个字节存储;“#”用于将错误号与错误信息分开;sql_state表示sql执行的状态;Error msg表示错误信息,最大512个字节长度。其中“#”和sql_state是客户端4.1协议增加的格式。

客户端之前协议error信息格式:

3 客户端之前协议error信息格式

       客户端之前的协议仅包含两个字段,错误号errno和错误信息Error msg。对应的字段存储结构与4.1协议一致。

Error信息传输格式:

       Error信息格式在网络层传输时,通过调用NET处理函数net_write_command()进行网络传输,传输格式如下所示:

4 error信息传输格式

       从传输格式可以看出,前三个字节存储packet的最大长度;1个字节存储下一个packet的编号;1个字节存储255,表示当前信息是错误信息,在数据信息解析过程中,用于判断是否为错误信息;ERROR内容时以上error信息格式封装的内容。特别说明的,255Error信息与其他信息的最大区别,其他信息在传输时的格式如上类似,但是没有该字段。

OK信息格式

       OK信息是SQL执行的成功状态信息,其数据格式根据客户端协议版本,有两种数据格式。

客户端协议4.1OK信息格式:

5 客户端4.1协议OK信息格式

       从协议格式来看,0是一个标志位,用于表示为OK信息;affect_rowsSQL执行影响的记录行数;id为查询id值;server_status表示SQL执行后,server的状态值;warn_countSQL执行产生的警告信息数,最大值为65535,大于这个数存储65535msg表示传输的信息,没有长度限制,如果信息过长,会进行分包传输。其中warn_count是在客户端协议4.1中增加的字段。

客户端协议4.0OK信息格式:

6 客户端4.0协议OK信息格式

       与协议4.1不同的是,4.0中不包含warn_count值。但是存储了server_status字段,用于记录serverSQL执行结束后的状态。

客户端之前协议OK信息格式:

7 OK信息格式

       对于之前的协议,OK信息格式没有server_statuswarn_count字段,仅包含基本的SQL执行信息。

       在传输时,传输格式类似于Error传输格式,不同的是,没有单独的255字节标示错误信息。然而在传输的信息中,OK的信息格式的第一个字节标志位,与255的意义是一样的,同样是用于标示数据内容为OK信息。

EOF信息格式

       EOF信息是用于表示传输数据结束的信息,根据客户端协议的版本,该信息也有两种格式。对于客户端协议4.1之前的EOF信息格式仅仅是发送信息标示一个字节(254),对于4.1协议,格式如下所示。

客户端协议4.1EOF信息格式:

8 客户端4.1协议EOF信息格式

       有信息格式可知,254标示EOF信息,在数据传输中,254信息类型为EOF信息;warn_countserver_status字段的含义与OK信息格式中的字段一致,不再赘述。

Metadata信息格式

       Metadata数据时数据库的表定义信息,主要是将数据表的各个字段进行封装,进行数据传输。Metadata信息的格式根据客户端协议的版本,也有两种格式。

客户端协议4.1Metadata信息格式:

       Metadata是对表定义的字段进行封装,以下仅将其中一个字段的详细信息格式给出,其他字段省略。

9 客户端4.1协议Metadata信息格式

       由以上格式可知,首先“def”三个字符是字段定义的开始;然后db_nametable_nameorg_table_namecol_nameorg_col_name分别表示数据库名、表名、原始表名、列名、原始表名;数字12是指还需要12个字节来存储后面的字段信息;charset_num表示字符集编号;length表示字段的长度;type表示字段的数据类型;flags表示字段的标志位;decimals表示数据的精度;之后两个字节存储0,用于以后扩展。完整的一个字段存储完成后,紧接着下一个字段的定义。

客户端之前协议Metadata信息格式:

 

10 Metadata信息格式

       Metadata信息格式各个字段的含义是:table_namecol_name分别表示表名和字段名;3表示接下来信息占用的字节数,即length需要占用3个字节;1type含义同上;后面的3表示flagsdecimals共占用三个字节。从以上信息格式来看,metadata在之前版本中存储的格式和字段较4.1协议,存在一些不足。首先字段定义之间没有严格的分割界限;其次每个字段的长度占用一个字节去存储占用的字节数,浪费空间;最后信息内容不够全面。而这些问题,在4.1协议中有了较好的改进。

       在处理函数send_result_set_metadata()中,根据flags的值,有几种不同的处理结果。其中一个是直接获取字段数,直接传输结果;另外就是发送EOF信息,表明数据传输结束。

ROW信息格式

       ROW信息的存储根据不同字段的存储类型,存储方式也不同,以下将根据不同的字段类型,分别给出具体字段的信息格式。

字符类型的NULL存储格式

       对于字段的数据为NULL的情况,在ROW数据封装时,仅存储251,占用1个字节。即在封装的数据包中,251表示NULL值。

字符类型存储格式

       字符类型主要包括MYSQL_TYPE_NULLMYSQL_TYPE_DECIMALMYSQL_TYPE_ENUMMYSQL_TYPE_SETMYSQL_TYPE_TINY_BLOBMYSQL_TYPE_MEDIUM_BLOBMYSQL_TYPE_LONG_BLOBMYSQL_TYPE_BLOBMYSQL_TYPE_GEOMETRYMYSQL_TYPE_STRINGMYSQL_TYPE_VAR_STRINGMYSQL_TYPE_VARCHARMYSQL_TYPE_BITMYSQL_TYPE_NEWDECIMAL,这些数据类型都是以字符的方式存储,特别注意的是文本类型与字符集有紧密的关系。字符类型根据长度,存储格式有多种格式,具体如下所示:

1、数据长度小于251

       数据长度小于251时,仅存储数据长度和数据内容。其中数据长度length占用1个字符。存储格式如下所示:

11 数据长度小于251的字符格式

2、数据长度大于等于251小于65536

       数据长度大于等于251并且小于65536时,存储格式包括三个部分:标志位252,表示数据长度范围;数据长度length,占用字节数与字符集有关;数据data内容。存储格式如下所示:

12 数据长度小于65536的字符格式

3、数据长度大于等于65536小于16M

       数据长度大于等于65536并且小于16M时,存储格式同第二种格式类似,仅标注位和数据长度占用的字节数不同。具体存储格式如下所示:

 

13 数据长度小于16M的字符格式

数据类型存储格式

       数据类型的存储首先调用对应的函数转化为字符类型(如tinylongfloatdecimal等类型),或者封装数据类型为字符类型(如timedatetime等)。最后处理转化为字符类型存储。

二进制数据存储格式

       二进制数据格式的存储没有字符集的问题,因此数据类型也不需要转化为字符类型,直接封装数据即可,存储格式同以上格式一致。其中对NULL值的存储格式有较大差异,存储格式根据字段位置计算,存储NULL值的源码如下所示:

bool Protocol_binary::store_null()

{

  uint offset= (field_pos+2)/8+1, bit= (1 << ((field_pos+2) & 7));

  /* Room for this as it's allocated in prepare_for_send */

  char *to= (char*) packet->ptr()+offset;

  *to= (char) ((uchar) *to | (uchar) bit);

  field_pos++;

  return 0;

}

结论

       通过对协议中各种信息的格式进行分析,进一步了解了MySQL服务器端数据封装和传输的协议。更深入的,结合客户端传输内容,分析传输内容,进行中间代理层处理,从而达到控制命令和数据的目的。

阅读(715) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~