mysql 通用响应数据包详解

OK_Packet


1. OK_Packet 的核心作用

  • 成功响应标识 :当客户端发送命令(如查询、设置变量等)成功执行后,服务器通过 OK_Packet 通知客户端操作已成功完成
  • 取代 EOF_Packet :从 MySQL 5.7.5 开始,OK_Packet 也用于标识结果集结束(End of File, EOF),原有的 EOF_Packet 被弃用。

2. OK_Packet 的协议结构

Packet 的 ​Payload(有效载荷)​ ​ 结构根据客户端的能力标志(Capability Flags)​​ 动态变化:

字段 数据类型 出现条件 描述
header int<1> 必选 固定值 0x00(OK)或 0xFE(EOF)
affected_rows int 必选 受影响的行数(如 UPDATE/DELETE)
last_insert_id int 必选 最后插入的自增 ID(如 INSERT)
status_flags int<2> CLIENT_PROTOCOL_41 能力启用 服务器状态标志(如事务状态)
warnings int<2> CLIENT_PROTOCOL_41 能力启用 警告数量
info string CLIENT_SESSION_TRACK 能力启用 人类可读的状态信息(如 SQL 提示)
session_state_info string status_flags 包含 SERVER_SESSION_STATE_CHANGED 会话状态变更信息(详细结构见下文)

3. 区分 OK 与 EOF

  • OK Packetheader = 0x00包长度 > 7
  • EOF Packetheader = 0xFE包长度 < 9
    (MySQL 5.7.5+ 通过此方式兼容旧版协议)

4. 向后兼容性处理

客户端/服务器组合 行为
旧客户端 + 新服务器 客户端不声明 CLIENT_DEPRECATE_EOF → 服务器发送传统 EOF_Packet
新客户端 + 旧服务器 服务器不支持新标志 → 发送传统 EOF_Packet
新客户端 + 新服务器 客户端声明 CLIENT_DEPRECATE_EOF → 服务器用 OK_Packet (0xFE) 代替 EOF

5. 会话状态跟踪(Session State Information)​

当会话状态变更时(如修改系统变量、切换数据库),session_state_info 包含多个状态块,结构如下:

lua 复制代码
+------+-------------------+--------------------------------+
| Type | Data              | 说明                           |
+------+-------------------+--------------------------------+
| 0x00 | 0x0F              | 跟踪类型:系统变量变更         |
|      | "autocommit"      | 变量名                         |
|      | "OFF"             | 新值                           |
+------+-------------------+--------------------------------+
| 0x01 | "test"            | 跟踪类型:切换 Schema          |
|      |                   | 数据库名(如 `USE test`)      |
+------+-------------------+--------------------------------+
| 0x02 | "1"               | 跟踪类型:启用状态跟踪         |
|      |                   | (ASCII '1' 表示启用)         |
+------+-------------------+--------------------------------+
  • 常见跟踪类型​:

    • SESSION_TRACK_SYSTEM_VARIABLES (0x00):系统变量变更(如 SET autocommit=OFF
    • SESSION_TRACK_SCHEMA (0x01):Schema 切换(如 USE test
    • SESSION_TRACK_STATE_CHANGE (0x02):会话跟踪功能启用状态变更

6. 示例说明

场景 ​:执行成功且启用 CLIENT_PROTOCOL_41 能力

响应内容​:

  • affected_rows = 0
  • last_insert_id = 0
  • status_flags = SERVER_STATUS_AUTOCOMMIT (表示开启自动提交)
  • warnings = 0
  • 无额外信息(infosession_state_info 为空)

关键总结

  1. 功能演进 :OK_Packet 在 MySQL 5.7.5+ 中一包两用(成功响应 + EOF 标识)。
  2. 动态结构 :包体结构由客户端能力标志 动态决定,需检查 CLIENT_PROTOCOL_41 等标志。
  3. 会话跟踪 :通过 session_state_info 实现精细化状态同步(如变量变更、数据库切换)。
  4. 兼容性 :新老协议通过 CLIENT_DEPRECATE_EOF 标志智能切换,确保平滑过渡。

​:实际实现参考 MySQL 源码中的 net_send_ok() 函数。

MySQL ERR_Packet 详解

ERR_Packet 是 MySQL 客户端/服务器协议中用于传递错误信息的数据包。当客户端请求发生错误时(如 SQL 语法错误、权限问题等),服务器会返回此包。


包结构(Payload)​
字段 类型/长度 描述
header int<1> ​**固定值 0xFF**​(标识这是一个 ERR_Packet)
error_code int<2> 错误代码 ​(如 1146 表示表不存在)
sql_state_marker(可选) string[1] 固定字符 #(仅在启用 CLIENT_PROTOCOL_41 时存在)
sql_state(可选) string[5] 5字符的 SQL 状态码 ​(如 42S02 表示表不存在,需启用协议 4.1)
error_message string<EOF> 人类可读的错误描述 ​(长度不超过 MYSQL_ERRMSG_SIZE=512 字节)

示例解析

示例数据(十六进制):
17 00 00 01 ff 48 04 23 48 59 30 30 30 4e 6f 20 74 61 62 6c 65 73 20 75 73 65 64

  1. 包头部

    • 17 00 00:包长度(23 字节,小端序)
    • 01:序列号(Sequence ID)
    • ff:ERR_Packet 标识(header=0xFF
  2. 错误代码

    • 48 04:小端序解析为 0x0448十进制错误码 1096
  3. SQL 状态(协议 4.1+)​

    • 23sql_state_marker(ASCII #
    • 48 59 30 30 30:ASCII 解码 → **SQL 状态 HY000**(通用错误)。
  4. 错误信息

    • 4e 6f 20 74 61 62 6c 65 73 20 75 73 65 64 → ASCII 解码为 **No tables used**。

最终错误信息 ​:
错误码 1096 (HY000): No tables used


关键说明
  1. 协议版本依赖

    • sql_state_markersql_state 仅在客户端支持 **CLIENT_PROTOCOL_41** 时发送(MySQL 4.1+ 默认启用)。
  2. 常见错误码

    错误码 SQL 状态 典型场景
    1064 42000 SQL 语法错误
    1146 42S02 表不存在
    1045 28000 用户权限认证失败
  3. 生成函数

    • 服务器内部通过 net_send_error_packet() 函数生成此包。

实际应用场景
  • 当客户端执行 SELECT * FROM non_existent_table; 时,服务器返回:

    • 错误码:1146
    • SQL 状态:42S02
    • 错误信息:Table 'test.non_existent_table' doesn't exist
  • 客户端库(如 Connector/Python、JDBC)会解析 ERR_Packet,抛出类似 mysql.connector.errors.ProgrammingError 的异常。

📌 ​总结​:ERR_Packet 是 MySQL 协议中高效传递错误的标准格式,包含机器可读的错误码和人类可读的描述,是客户端错误处理的核心机制。

MySQL EOF_Packet 详解

核心作用

EOF_Packet 是 MySQL 协议中用于标记查询结果结束的包(如结果集传输完毕或命令执行结束)。在 MySQL 5.7.5+ 中已被 OK_Packet 取代,但为兼容旧版协议仍可能发送。


包结构(Payload)
字段 类型/长度 出现条件 描述
header int<1> 必选 固定值 0xFE(标识 EOF)
warnings int<2> 启用 CLIENT_PROTOCOL_41 警告数量
status_flags int<2> 启用 CLIENT_PROTOCOL_41 服务器状态标志(如事务状态)

关键限制 ​:包总长度必须 ​​< 9 字节​(否则可能被误判为其他数据类型)。


协议演进与兼容性
场景 行为
MySQL < 5.7.5 使用 EOF_Packet 标记结果结束
MySQL ≥ 5.7.5 默认用 OK_Packet 取代 EOF_Packet(支持更多功能如会话状态跟踪)
旧客户端 + 新服务器 服务器降级发送 EOF_Packet(若客户端不支持 CLIENT_DEPRECATE_EOF 标志)
新客户端 + 旧服务器 服务器始终发送 EOF_Packet

示例解析

示例数据(十六进制):
05 00 00 05 fe 00 00 02 00

  1. 包头解析​:

    • 05 00 00:包长度(5 字节,小端序)
    • 05:序列号(Sequence ID)
    • fe:EOF_Packet 标识(header=0xFE
  2. 协议 4.1 扩展字段​:

    • 00 00:警告数 = 0
    • 02 00:状态标志 = SERVER_STATUS_AUTOCOMMIT(小端序 0x0002

含义 ​:

"结果集已结束,无警告,自动提交已启用"


关键注意点
  1. 与 OK_Packet 的区分​:

    • 检查包头:0xFE + 包长 < 9 字节 → EOF_Packet
    • 若包长 ≥ 9 字节且包头为 0x00 → OK_Packet(含更多数据)
  2. 弃用警告​:

    • MySQL 5.7.5+ 优先使用 OK_Packet(因支持会话跟踪等新特性)
    • 仅在兼容旧客户端时发送 EOF_Packet
  3. 风险场景​:

    • 解析时若未检查包长,可能将 **其他数据中的 0xFE** 误判为 EOF(文档特别警告需验证包长 < 9)

函数关联
  • 服务器生成此包调用:**net_send_eof()**

总结​:EOF_Packet 是 MySQL 协议的历史遗留标记,现代版本(5.7.5+)应优先处理 OK_Packet。理解其结构及兼容逻辑对开发数据库中间件或协议分析工具至关重要。

相关推荐
qq_3923971234 分钟前
Redis常用操作
数据库·redis·wpf
一只fish2 小时前
MySQL 8.0 OCP 1Z0-908 题目解析(17)
数据库·mysql
花好月圆春祺夏安3 小时前
基于odoo17的设计模式详解---装饰模式
数据库·python·设计模式
A__tao3 小时前
SQL 转 Java 实体类工具
java·数据库·sql
m0_653031363 小时前
腾讯云认证考试报名 - TDSQL数据库交付运维专家(TCCE PostgreSQL版)
运维·数据库·腾讯云
小马哥编程4 小时前
【iSAQB软件架构】架构决策记录-ADR
数据库·架构·系统架构·设计规范
萧鼎4 小时前
深度探索 Py2neo:用 Python 玩转图数据库 Neo4j
数据库·python·neo4j
m0_653031365 小时前
腾讯云认证考试报名 - TDSQL数据库交付运维专家(TCCE MySQL版)
运维·数据库·腾讯云
power 雀儿5 小时前
集群聊天服务器---MySQL数据库的建立
服务器·数据库·mysql
骑着王八撵玉兔7 小时前
【性能优化与架构调优(二)】高性能数据库设计与优化
数据库·性能优化·架构