mysql响一下_MySQL 通信协议

MySQL 通信协议介绍

1、数据类型

了解MySQL协议包之前必需先知道其数据类型

1.1 Integer Types 整数类型

(1)定长整型

固定长度, 小端编码, 有下面几种(括号内的代表所占字节数):

int<1>

int<2>

int<3>

int<4>

int<6>

int<8>

(2)变长整型

可能长度为1, 3, 4, 9 个字节, 实际长度取决于数值的大小.记为 int

编码过程, 记数值为N:

1.若 N < 251, 则编码为单字节

2.若 251 <= N < 2^16, 则编码为 0xfc + 2-byte integer

3.若 2^16 <= N < 2^24, 则编码为 0xfd + 3-byte integer

4.若 2^24 <= N < 2^64, 则编码为0xfe + 8-byte integer

解码过程, 先看第一个字节, 记其值为N1,

1.若 N1 <= 0xfb, 则说明该整数就是N1

2.若 N1 = 0xfc,则说明接下来2字节也是该整数的部分, 取出加上0xfc即为原数值

3.若 N1 = 0xfd, ...

4.若 N1 = 0xfe, ...

值得注意的是, 当协议包的第一个字节为0xfe时, 应该检查接下来是否有8个字节, 若没有则说明该协议包可能是EOF_PACKET

1.2 String Types 字符串类型

(1)FixedLengthString

定长字符串,记为 string

(2)NulTerminatedString

由NUL标识结束的字符串, NUL即0x00,记为string

(3)VariableLengthString

变长字符串, 长度由别的其它字段决定或者运行时动态计算出来的,记为string

(4)LengthEncodedString

长度编码的字符串, 即其前面有个整型int说明接下来的字符串的长度, 起始就是VariableLengthString,记为string

(5)RestOfPacketString

若一个字符串是一个协议包的最后一个字段, 那该字符串的长度当然就等于包长 - 当前位置,记为string

2.MySQL协议包

客户端或服务端要发消息给对方时:

1.把消息分成若干个长度小于 2^24-1(即16 M)的消息

2.给每个消息前面加一个4字节包头.

如下:

Type

Name

Description

int<3>

payload_length

payload字段的长度

int<1>

sequence_id

序列号

string

payload

payload包体

例如CMD_QUIT的整包字节序列为:01 00 00 00 01

1.通用响应报文

(1) OK_Packet

表示操作成功的报文,5.7开始用该报文替代EOF_Packet

报文格式:

61f79a93aa853e2efc94ae23d38a4c96.png

判断时OK还是EOF规则:

OK: header = 0 and length of packet > 7

EOF: header = 0xfe and length of packet < 9

(2) ERR_Packet

表示操作失败的报文. It contains a SQL state value if CLIENT_PROTOCOL_41 is enabled.

报文格式:

f57fe57e9fef498f1b04e21dd51dad45.png

(3) EOF_Packet

If CLIENT_PROTOCOL_41 is enabled, the EOF packet contains a warning count and status flags.

EOF报文用来表示多个报文组成的一个报文簇的结束,比如当客户端发送查询命令到mysql server时,mysql会按顺序回复以下报文:

1.ResultSetHeaderPacket  --报文中携带了查询结果包含的字段的个数N,以及其它一些信息

2.FieldPacket * N -- N个FieldPacket,每一个都表示一个字段的定义

3.EOF Packet -- 表示字段定义的所有报文已发送完毕

4.RowDataPacket * M -- 每个报文表示一行数据

5.EOF Packet -- 表示行数据报文发送完毕。

报文格式:

26e3003e386029ca988e9bc3ff64871d.png

EOF_Packet和OK_Packet 都是用来表示一个query的结果的尾包,5.7.5版本EOF_Packet就不在使用了

上面的报文中涉及到的statu_flag取值及含义如下:

106c01fe9b825b50fcbecc373f0902fb.png

2.连接建立阶段报文

(1) Handshake Packet(Server -> Client)

握手报文,当客户端连接服务端时,当TCP连接建立完成后,Server会主动向Client发送一个握手协议报文,里面携带了Server的相关信息和权能标识,关于权能标识(capabilities flag),具体可以去这里查

1 [0a] protocol version -- 协议版本

string[NUL] server version -- Server版本

4 connection id

string[8] auth-plugin-data-part-1

1 [00] filler -- 填充,总是0x00

2 capability flags (lower 2 bytes) --Server权能标识

if more data in the packet:

1 character set -- 连接所使用的字符集

2 status flags

2 capability flags (upper 2 bytes)

if capabilities & CLIENT_PLUGIN_AUTH {

1 length of auth-plugin-data

} else {

1 [00]

}

string[10] reserved (all [00])

if capabilities & CLIENT_SECURE_CONNECTION {

string[$len] auth-plugin-data-part-2 ($len=MAX(13, length of auth-plugin-data - 8))

if capabilities & CLIENT_PLUGIN_AUTH {

string[NUL] auth-plugin name

}

(2)HandShake Response Packet(Client -> Server)

客户端收到Handshake Packet后,生成一个Response并发给Server,里面携带客户端的权能标识,用户名等相关的信息,如果Handshake Packet中的权能标识中带有client_protocol_41标识位,那么客户端将生成的Response为HandShake Response41,否则生成的为HandShake Response320,我们这里就不管HandShake Response320,因为现在的Server基本都会支持这个

HandShake Response41格式:

4 capability flags, CLIENT_PROTOCOL_41 always set -- 客户端的权能标识

4 max-packet size -- 最大包大小

1 character set -- 字符集

string[23] reserved (all [0]) -- 保留,总是0

string[NUL] username -- 用户名

if capabilities & CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA { -- 看了mycat的源码才知道,这个其实是密码

lenenc-int length of auth-response

string[n] auth-response

} else if capabilities & CLIENT_SECURE_CONNECTION {

1 length of auth-response

string[n] auth-response

} else {

string[NUL] auth-response

}

if capabilities & CLIENT_CONNECT_WITH_DB { -- 连接默认数据库名

string[NUL] database

}

if capabilities & CLIENT_PLUGIN_AUTH {

string[NUL] auth plugin name

}

if capabilities & CLIENT_CONNECT_ATTRS {

lenenc-int length of all key-values

lenenc-str key

lenenc-str value

if-more data in 'length of all key-values', more keys and value pairs

}

3.普通请求/响应报文

在连接建立后,Client就可以发送普通的查询或者其它命令给Server了,下面对这些命令进行介绍

1.COM_SLEEP 请求

这个是Server内部的命令,不是客户端给服务端发的,忽略即可

1 [00] COM_SLEEP

2.COM_QUIT 请求

当客户端要关闭连接时,发送该命令到Server

1 [01] COM_QUIT

返回:要么是OK Packet,要么就连接关闭

3.COM_INIT_DB 请求

修改连接默认的schema

1 [02] COM_INIT_DB

string[EOF] schema name -- 数据库名

返回:OK Packet 或者ERR Packet

4.COM_QUERY 请求

发送普通查询请求,这个查询是立即执行的,因此预编译不是发这个命令的

1 [03] COM_QUERY

string[EOF] the query the server shall execute -- sql语句

返回:COM_QUERY_RESPONSE Packet

5.COM_QUERY_PACKET 响应

COM_QUERY的响应报文,该报文只是个逻辑上的报文,其组成为以下几个中的一个:

ERR Packet

OK Packet

ResultSet Packet -- 普通查询结果

LOAD DATA INFILE REQUEST Packet

6.ResultSetPacket 响应

普通查询结果,也是一个逻辑上的报文,其由以下部分组成:

1.ResultSetHeaderPacket -- 只包含一个int的整数(记为N,表示结果字段的个数)和一个8字节的extra附加信息

2.ColumnDefinitionPacket * N -- N个ColumnDefinitionPacket ,每个ColumnDefinitionPacket表示一个字段的信息,其格式如下:

lenenc_str catalog

lenenc_str schema

lenenc_str table

lenenc_str org_table

lenenc_str name

lenenc_str org_name

lenenc_int length of fixed-length fields [0c]

2 character set

4 column length

1 type

2 flags

1 decimals

2 filler [00] [00]

if command was COM_FIELD_LIST {

lenenc_int length of default-values

string[$len] default values

}

3.EOF Packet 表示所有ColumnDefinitionPacket都发送完了,接下来将发行数据了

4.任意个RowDataPacket,每一个代表一行数据,其中NULL用0xfb(251)表示,其格式如下:

lenenc_str field1's value -- 第一个字段的值

lenenc_str field2's value -- 第二个字段的值

...

lenenc_str fieldN's value -- 第N个字段的值

5.EOF Packet,表示ResultSetPacket完毕,若此包中的SERVER_MORE_RESULT_EXISTS被设置,则则说明接下来还有ResultSetPacket,又回到第一步开始接收...

整个查询过程如下图:

14e03abc2c545e2979f05998c2f5842f.png

7.COM_FIELD_LIST 请求

获取字段定义,5.7.11开始已弃用

1 [04] COM_FIELD_LIST

string[NUL] table -- 表名

string[EOF] field wildcard 字段通配符

返回:COM_FIELD_LIST RESPONSE Packet

8.COM_FIELD_LIST 响应

COM_FIELD_LIST的响应报文,该报文是一个逻辑报文,其组成为以下一种:

1.ERR packet

2.任意个ColumnDefinitionPacket加一个EOFPacket

9.COM_CREATE_DB 请求

创建数据库请求

1 [05] COM_CREATE_DB

string[EOF] schema name -- 数据库名

返回:OK Packet或者ERR Packet

10.COM_DROP_DB 请求

删除数据库请求

1 [06] COM_DROP_DB

string[EOF] schema name -- 数据库名

返回:OK Packet 或者 ERR Packet

11.COM_REFRESH 请求

Flush ... 和RESET ... 语句的实现命令,从5.7.11版本开始已弃用,改用COM_QUERY,执行FLUSH语句或者

1 [07] COM_REFRESH

1 sub_command -- 命令,取值见下

sub_command取值:

a8f0c11fd649f958bda95d0c63ba0ef7.png

返回:OK Packet或者ERR Packet

12.COM_SHUTDOWN 请求

shutdown mysql server的请求,5.7.9已弃用,8.0已移除,执行mysqladmin shutdown时发送该命令

1 [08] COM_SHUTDOWN

if more data {

1 shutdown type

}

shutdown type取值:

de00f94399acb87da60311b6b55f53dd.png

返回:OK Packet或者ERR packet

13.COM_STATISTICS 请求

获取human readable的mysql server统计信息,执行mysqladmin status时发送该命令

1 [09] COM_STATISTICS

返回:string

14.COM_PROCESS_INFO 请求

get a list of active threads,执行show processlist 或者 mysqladminproesslist时发送该命令

1 [0a] COM_PROCCESS_INFO

返回:ResultSetPacket 或者ERR Packet

15.COM_CONNECT 请求

mysql server 内部命令,5.7.11版本弃用,使用COM_QUERY替代

16.COM_PROCESS_KILL 请求

关闭连接

1 [0c] COM_PROCCESS_KILL

4 connection id -- 连接ID,这个是在HandShake Packet传过来的

返回:OK Packet或者ERR Packet

16.COM_DEBUG 请求

COM_DEBUG triggers a dump on internal debug info to stdout of the mysql-server.The SUPER privilege is required for this operation.执行mysqladmin debug时发送该命令

1 [0d] COM_DEBUG

返回:EOF Packet或者ERR Packet

17.COM_PING 请求

心跳检测

1 [0e] COM_PING

返回:OK Packet

18.COM_TIME

mysql server内部命令

19.COM_DELAYED_INSERT

mysql server内部命令

20.COM_CHANGE_USER 请求

更改当前连接的用户并重置连接状态,包括user variables、临时表和预编译语句等等...

1 [11] COM_CHANGE_USER

string[NUL] user

if capabilities & SECURE_CONNECTION {

1 auth-response-len

string[$len] auth-response

} else {

string[NUL] auth-response

}

string[NUL] schema-name

if more data {

2 character-set

if capabilities & CLIENT_PLUGIN_AUTH {

string[NUL] auth plugin name

}

if capabilities & CLIENT_CONNECT_ATTRS) {

lenenc-int length of all key-values

lenenc-str key

lenenc-str value

if-more data in 'length of all key-values', more keys and value pairs

}

}

21.COM_RESET_CONNECTION 请求

Resets the session state; more lightweight than COM_CHANGE_USER because it does not close and reopen the connection, and does not re-authenticate

1 [1f] COM_RESET_CONNECTION

返回:OK Packet或者ERR Packet

22.COM_DAEMON 请求

mysql server内部命令

23.COM_STMT_PREPARE 请求

预编译语句,执行conn.preparedStatement(sql)时发送该命令

1 the COM_STMT_PREPARE command

string query statement -- sql语句

返回:COM_STMT_PREPARED OK Packet或者Err Packet

24.COM_STMT_PREPARE Response 响应

预编译成功时的响应报文,时逻辑报文,其由多个报文组成:

1.第一个报文包含预编译成功信息,其格式如下:

1 status, [00]=OK --成功标志

4 statementId -- 预编译的语句ID

2 number of columns -- 字段个数

2 number of params -- 参数个数

1 reserved, always 00 -- 保留

2 number of warnings -- 警告个数

2.如果上面的参数个数(记为N)大于0的话,那么接下来会有N个ColumnDefinitionPacket加上一个EOF Packet会被发送

3.如果上面的字段个数(记为M)大于0的话,那么接下来会有M个ColumnDefinitionPacket加上一个EOF Packet会被发送

25.COM_STMT_SEND_LONG_DATA请求

发送参数值给预编译语句,预编译中有几个?就得发几个该请求,并且都得在COM_STMT_EXECUTE之前发送

1 [18] COM_STMT_SEND_LONG_DATA

4 statement-id -- 预编译语句ID

2 param-id -- 参数ID

n data -- 参数值

返回:无返回

26.COM_STMT_EXECUTE请求

执行预编译语句

1 [17] COM_STMT_EXECUTE

4 stmt-id -- 语句ID

1 flags

4 iteration-count, always 1

if num-params > 0:

n NULL-bitmap, length: (num-params+7)/8

1 new-params-bound-flag

if new-params-bound-flag == 1:

n type of each parameter, length: num-params * 2

n value of each parameter

flags取值:

844bb05ce48546aaf3483afa215e5a2f.png

返回:COM_STMT_EXECUTE Response

27.COM_STMT_EXECUTE Response响应

COM_STMT_EXECUTE 的响应报文,是下面三者之一:

1.OK Packet -- 执行update时

2.Err Packet

3.Binary Protocol ResultSet Packet --执行查询时

Binary Protocol ResultSet

binary protocol result和之前讲的ResultSetPacket相似,

28.COM_STMT_CLOSE请求

关闭预编译语句,该请求无响应

1 [19] COM_STMT_CLOSE

4 statement-id -- 预编译语句ID

29.COM_STMT_RESET请求

清空由COM_STMT_SEND_LONG_DATA发送的所有参数值,并关闭由COM_STMT_EXECUTE打开的CURSOR

1 [1a] COM_STMT_RESET

4 statement-id

返回:OK Packet或者ERR Packet

// TODO 未完待补充

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值