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<lenenc>
编码过程, 记数值为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<fix>
(2)NulTerminatedString
由NUL标识结束的字符串, NUL即0x00,记为string<NUL>
(3)VariableLengthString
变长字符串, 长度由别的其它字段决定或者运行时动态计算出来的,记为string<var>
(4)LengthEncodedString
长度编码的字符串, 即其前面有个整型int<lenenc>说明接下来的字符串的长度, 起始就是VariableLengthString,记为string<lenenc>
(5)RestOfPacketString
若一个字符串是一个协议包的最后一个字段, 那该字符串的长度当然就等于包长 - 当前位置,记为string<EOF>
2.MySQL协议包
客户端或服务端要发消息给对方时:
1.把消息分成若干个长度小于 2^24-1(即16 M)的消息
2.给每个消息前面加一个4字节包头.
如下:
Type | Name | Description |
int<3> | payload_length | payload字段的长度 |
int<1> | sequence_id | 序列号 |
string<var> | payload | payload包体 |
例如CMD_QUIT的整包字节序列为:01 00 00 00 01
1.通用响应报文
(1) OK_Packet
表示操作成功的报文,5.7开始用该报文替代EOF_Packet
报文格式:
判断时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.
报文格式:
(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 -- 表示行数据报文发送完毕。
报文格式:
EOF_Packet和OK_Packet 都是用来表示一个query的结果的尾包,5.7.5版本EOF_Packet就不在使用了
上面的报文中涉及到的statu_flag取值及含义如下:
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<lenenc>的整数(记为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,又回到第一步开始接收...
整个查询过程如下图:
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取值:
返回: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取值:
返回:OK Packet或者ERR packet
13.COM_STATISTICS 请求
获取human readable的mysql server统计信息,执行mysqladmin status时发送该命令
1 [09] COM_STATISTICS
返回:string<EOF>
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<EOF> 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取值:
返回: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 未完待补充
相关推荐
内容概要:本文详细介绍了基于MATLAB GUI界面和卷积神经网络(CNN)的模糊车牌识别系统。该系统旨在解决现实中车牌因模糊不清导致识别困难的问题。文中阐述了整个流程的关键步骤,包括图像的模糊还原、灰度化、阈值化、边缘检测、孔洞填充、形态学操作、滤波操作、车牌定位、字符分割以及最终的字符识别。通过使用维纳滤波或最小二乘法约束滤波进行模糊还原,再利用CNN的强大特征提取能力完成字符分类。此外,还特别强调了MATLAB GUI界面的设计,使得用户能直观便捷地操作整个系统。 适合人群:对图像处理和深度学习感兴趣的科研人员、高校学生及从事相关领域的工程师。 使用场景及目标:适用于交通管理、智能停车场等领域,用于提升车牌识别的准确性和效率,特别是在面对模糊车牌时的表现。 其他说明:文中提供了部分关键代码片段作为参考,并对实验结果进行了详细的分析,展示了系统在不同环境下的表现情况及其潜在的应用前景。
嵌入式八股文面试题库资料知识宝典-计算机专业试题.zip
嵌入式八股文面试题库资料知识宝典-C and C++ normal interview_3.zip
内容概要:本文深入探讨了一款额定功率为4kW的开关磁阻电机,详细介绍了其性能参数如额定功率、转速、效率、输出转矩和脉动率等。同时,文章还展示了利用RMxprt、Maxwell 2D和3D模型对该电机进行仿真的方法和技术,通过外电路分析进一步研究其电气性能和动态响应特性。最后,文章提供了基于RMxprt模型的MATLAB仿真代码示例,帮助读者理解电机的工作原理及其性能特点。 适合人群:从事电机设计、工业自动化领域的工程师和技术人员,尤其是对开关磁阻电机感兴趣的科研工作者。 使用场景及目标:适用于希望深入了解开关磁阻电机特性和建模技术的研究人员,在新产品开发或现有产品改进时作为参考资料。 其他说明:文中提供的代码示例仅用于演示目的,实际操作时需根据所用软件的具体情况进行适当修改。
少儿编程scratch项目源代码文件案例素材-剑客冲刺.zip
少儿编程scratch项目源代码文件案例素材-几何冲刺 转瞬即逝.zip
内容概要:本文详细介绍了基于PID控制器的四象限直流电机速度驱动控制系统仿真模型及其永磁直流电机(PMDC)转速控制模型。首先阐述了PID控制器的工作原理,即通过对系统误差的比例、积分和微分运算来调整电机的驱动信号,从而实现转速的精确控制。接着讨论了如何利用PID控制器使有刷PMDC电机在四个象限中精确跟踪参考速度,并展示了仿真模型在应对快速负载扰动时的有效性和稳定性。最后,提供了Simulink仿真模型和详细的Word模型说明文档,帮助读者理解和调整PID控制器参数,以达到最佳控制效果。 适合人群:从事电力电子与电机控制领域的研究人员和技术人员,尤其是对四象限直流电机速度驱动控制系统感兴趣的读者。 使用场景及目标:适用于需要深入了解和掌握四象限直流电机速度驱动控制系统设计与实现的研究人员和技术人员。目标是在实际项目中能够运用PID控制器实现电机转速的精确控制,并提高系统的稳定性和抗干扰能力。 其他说明:文中引用了多篇相关领域的权威文献,确保了理论依据的可靠性和实用性。此外,提供的Simulink模型和Word文档有助于读者更好地理解和实践所介绍的内容。
嵌入式八股文面试题库资料知识宝典-2013年海康威视校园招聘嵌入式开发笔试题.zip
少儿编程scratch项目源代码文件案例素材-驾驶通关.zip
小区开放对周边道路通行能力影响的研究.pdf
内容概要:本文探讨了冷链物流车辆路径优化问题,特别是如何通过NSGA-2遗传算法和软硬时间窗策略来实现高效、环保和高客户满意度的路径规划。文中介绍了冷链物流的特点及其重要性,提出了软时间窗概念,允许一定的配送时间弹性,同时考虑碳排放成本,以达到绿色物流的目的。此外,还讨论了如何将客户满意度作为路径优化的重要评价标准之一。最后,通过一段简化的Python代码展示了遗传算法的应用。 适合人群:从事物流管理、冷链物流运营的专业人士,以及对遗传算法和路径优化感兴趣的科研人员和技术开发者。 使用场景及目标:适用于冷链物流企业,旨在优化配送路线,降低运营成本,减少碳排放,提升客户满意度。目标是帮助企业实现绿色、高效的物流配送系统。 其他说明:文中提供的代码仅为示意,实际应用需根据具体情况调整参数设置和模型构建。
少儿编程scratch项目源代码文件案例素材-恐怖矿井.zip
内容概要:本文详细介绍了基于STM32F030的无刷电机控制方案,重点在于高压FOC(磁场定向控制)技术和滑膜无感FOC的应用。该方案实现了过载、过欠压、堵转等多种保护机制,并提供了完整的源码、原理图和PCB设计。文中展示了关键代码片段,如滑膜观测器和电流环处理,以及保护机制的具体实现方法。此外,还提到了方案的移植要点和实际测试效果,确保系统的稳定性和高效性。 适合人群:嵌入式系统开发者、电机控制系统工程师、硬件工程师。 使用场景及目标:适用于需要高性能无刷电机控制的应用场景,如工业自动化设备、无人机、电动工具等。目标是提供一种成熟的、经过验证的无刷电机控制方案,帮助开发者快速实现并优化电机控制性能。 其他说明:提供的资料包括详细的原理图、PCB设计文件、源码及测试视频,方便开发者进行学习和应用。
基于有限体积法Godunov格式的管道泄漏检测模型研究.pdf
嵌入式八股文面试题库资料知识宝典-CC++笔试题-深圳有为(2019.2.28)1.zip
少儿编程scratch项目源代码文件案例素材-几何冲刺 V1.5.zip
Android系统开发_Linux内核配置_USB-HID设备模拟_通过root权限将Android设备转换为全功能USB键盘的项目实现_该项目需要内核支持configFS文件系统
C# WPF - LiveCharts Project
少儿编程scratch项目源代码文件案例素材-恐怖叉子 动画.zip
嵌入式八股文面试题库资料知识宝典-嵌⼊式⼯程师⾯试⾼频问题.zip