• MySQL源码分析之 通信协议(一)


    MySQL源码分析之 通信协议(一)

    mysql 通信协议用于 mysql 客户端和服务器之间的通讯,通过以下几种方式实现:

     1)、接口: (Connector/C, Connector/J, 等) 即平时我们所说的 JDBC ODBC 等接口

     2)、mysql 中间件

     3)、主服务器和从服务器之间的通信

    mysql 协议支持一下几点功能:

     1)、使用 SSL 的透明加密

     2)、透明压缩

     3)、连接阶段,进行身份验证和数据交换的能力

     4)、执行阶段,接收客户端发来的命令并执行他们

    交互过程:

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

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

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

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

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

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

     

    基本类型:

    1、整型

    整型分为固定长度的整型和可变长度的整型(变长在这里指的是存储长度)。

    固定长度类型属于无符号整型,分别有1、2、3、4、6、8字节长度,使用小字节序传输最低有效字节排在第一位。以3字节长度整型为例可以查看 int3store()

    变长整型,可能占用1、3、4、9个字节,具体取决于其数值。把一个整型值转换为一个可变字节长度存储需要如下操作:

    因此,如果需要将变长存储的整型转化为数值,需要检查第一个字节。

    注意: 如果数据包的第一个字节是长度编码的整数,其字节值为0xFE,则必须检查数据包的长度,以验证其是否有足够的空间容纳8字节整数。如果不是,它可能是一个EOF数据包。 

    2、字符串

    字符串在协议中有以下几种形势:

    1)、固定长度的字符串,具有已知的硬编码长度。例如,ERR数据包的sql状态总是5字节长

    2)、字符串长度不固定,当遇到'NULL'(0x00)字符时结束。

    3)、字符串的长度由另一个字段确定,或在运行时计算

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

    5)、如果字符串是数据包的最后一个组成部分,则可以从数据包的总长度减去当前位置来计算其长度。

    报文结构:
    如果 MySQL 客户端和服务器想发送数据,需要将数据拆为2**24大小的数据包(即16M)因此客户端和服务器之间以最大16M 的数据包进行交换。会为每个数据块预先添加一个数据包头。因此可以这么理解:报文分为消息头和消息体两部分,其中消息头占用固定的4个字节,消息体长度由消息头中的长度字段决定,报文结构如下:

      

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

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

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

    通用响应包(服务响应报文):

    响应包可以分为三种,OK_Packet、 ERR_Packet、EOF_Packet。从MySQL 5.7.5开始,OK数据包也被用来表示EOF,EOF数据包被弃用。如果设置了CLIENT_PROTOCOL_41,即MySQL 版本大于4.1。 

    该数据包包含一个警告计数。

    1、OK 响应报文

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

    如果 header = 0 并且packer 长度大于7,说明这个包是 OK 数据包

    如果 header = 0xFE 并且 packer 长度小于9,说明这个包是 EOF 包。 

    affecred rows:受影响行数,当执行 INSERT/UPDATE/DELETE 语句时所影响的数据行数

    last_insert_id: 值为AUTO_INCREMENT索引字段生成,如果没有索引字段,则为0x00。注意:当INSERT插入语句为多行数据时,该索引ID值为第一个插入的数据行索引值,而非最后一个

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

    warnings:   告警次数,即告警发生的次数

    session state info:  会话状态信息

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

    **会话状态信息**

    状态变化信息作为一组状态变化块在OK数据包中发送,这些状态变化块由以下部分组成:

    类型:数据的类型,可以查看 enum_session_state_type.。 数据,会话信息改变的数据

     

    enum enum_session_state_type {
      SESSION_TRACK_SYSTEM_VARIABLES, /**< Session system variables */
      SESSION_TRACK_SCHEMA,           /**< Current schema */
      SESSION_TRACK_STATE_CHANGE,     /**< track session state changes */
      SESSION_TRACK_GTIDS,            /**< See also: session_track_gtids */
      SESSION_TRACK_TRANSACTION_CHARACTERISTICS, /**< Transaction chistics */
      SESSION_TRACK_TRANSACTION_STATE            /**< Transaction state */
    };

     数据字段的解释取决于类型值。

    1)、SESSION_TRACK_SYSTEM_VARIABLES   会话跟踪系统变量

    2)、SESSION_TRACK_SCHEMA  会话跟踪模式

    3)、SESSION_TRACK_STATE_CHANGE 会话跟踪状态更改。 指示会话状态是否发生更改的标志字节。此标志表示为ASCII值

    2、ERR 响应报文 

    错误包意味着产生了错误信息,在 MySQL4.1版本之后,它包含一个 SQL 状态值,错误文本大小不能超过 Error texts cannot exceed。 代码函数 net_send_error_packet()

    header: 消息头,ERR 报文问 0xFF

    error-code:  错误码,定义在源代码/include/mysqld_error.h头文件中

    sql_state_marker:  服务器状态标志,恒为'#'字符

    sql_sate: 服务器状态,服务器将错误编号通过mysql_errno_to_sqlstate函数转换为状态值,状态值由5字节的ASCII字符组成,定义在源代码/include/sql_state.h头文件中

    error_message: 错误信息,错误消息字符串到达消息尾时结束,长度可以由消息头中的长度值计算得出。消息长度为0-512字节

    3、EOF 响应报文 

    如果启用了CLIENT_PROTOCOL_41,则EOF数据包包含警告计数和状态标志。

    在 mysql 的通信协议中,EOF 数据包和 OK 数据包是一样的目的,用来标记一个查询结果的结束。在 MySQL5.7因为 OK 数据包发生了更改(如会话状态跟踪),为了避免 EOF 数据发生重复更改,在 MySQL5.7.5之后弃用 OK 数据包。

    EOF_数据包可能出现在可能出现Protocol::engthCodedInteger的地方。您必须检查数据包长度是否小于9,以确保它是EOF_数据包。

    warnings: 告警计数,服务器告警数量,在所有数据都发送给客户端后该值才有效。

    status_flags: 状态标志位,包含类似SERVER_MORE_RESULTS_EXISTS这样的标志位。

    :由于EOF值与其它Result Set结构共用1字节,所以在收到报文后需要对EOF包的真实性进行校验,校验条件为:

    • 第1字节值为0xFE
    • 包长度小于9字节

    未完待续。。。。

  • 相关阅读:
    java冒泡算法和选择排序法
    JDBC操作数据库,比如修改电商数据库中的分类的id,让各商品随机
    RF使用
    安装RF框架(基于Python)
    selenium+java的常使用的一些操作
    selenium的常用操作
    selenium的8种定位方式(java举例)
    服务管理
    Linux软件安装
    项目依赖
  • 原文地址:https://www.cnblogs.com/jkin/p/16257513.html
Copyright © 2020-2023  润新知