MySQL数据包

76 阅读3分钟

MySQL 客户端与服务器之间通信的基本单位:数据包(Packets)​

  1. 核心概念:分包传输

    • 当客户端或服务器需要发送数据时,如果数据量很大,它不会一次性发送完。
    • 它会将数据 ​拆分成较小的块,每个块就是一个 Packet
    • 每个 Packet 的最大有效载荷(Payload)是 ​16,777,215 字节​(即 2²⁴ - 1 字节,或大约 16MB)。
  2. Packet 结构
    每个 Packet 由两部分组成:

    • Packet Header (包头部 - 4 字节):​

      • ​**payload_length (3 字节):​​ 指定紧随其后的 ​Payload 部分的实际长度​(单位:字节)。这 3 个字节是 ​小端字节序**。
      • ​**sequence_id (1 字节):​​ ​序列号**。用于标识数据包的顺序,防止乱序或丢失。发送方每发送一个 Packet,这个 ID 就递增一次(从 0 开始)。在每个新的命令开始时(命令阶段),序列号会重置为 0。这个 ID 允许回绕(超过 255 后又从 0 开始)。
    • Payload (有效载荷 - 长度由 payload_length 指定):​​ 实际要传输的数据内容。这部分的结构取决于具体的命令或响应(例如 SQL 查询、查询结果、错误信息、认证信息等)。

  3. 发送超过 16MB 的数据

    • 如果数据总长度正好等于或超过 16,777,215 字节,发送方需要拆分成多个 Packet。

    • 第一个 Packet:​

      • payload_length 设置为 0xFFFFFF(即 16,777,215 的十六进制表示,对应 3 个字节的 FF FF FF)。
      • 只包含数据的前 16,777,215 字节作为 Payload。
    • 后续 Packet(s):​

      • 发送剩余的数据。
      • 每个后续 Packet 的 payload_length 是其实际 Payload 的长度(小于或等于 16,777,215 字节)。
      • sequence_id 会依次递增。
    • 最后一个 Packet:​

      • payload_length 小于 16,777,215 字节(即不是 FF FF FF),表示这是最后一个分块。
  4. 例子说明
    文档给出了发送 ​16,777,215 字节​ 数据的极端例子:

    • Packet 1:​FF FF FF 00 + (16,777,215 字节的 Payload)

      • FF FF FF = payload_length = 16,777,215
      • 00 = sequence_id = 0
    • 紧接着发送 ​1 字节​:

    • Packet 2:​01 00 00 01 + (1 字节的 Payload)

      • 01 00 00 = payload_length = 1 (小端字节序:低位在前,实际值是 00 00 01 = 1)
      • 01 = sequence_id = 1 (在上一个包的 0 基础上递增)
  5. 文档结构说明

    • 文档描述了如何在文档中表示数据包:主要定义其 ​Payload​ 的结构(类型、字段含义)。
    • 提供示例时会包含完整的 Packet(包括 Header)。
    • 强调某些字段或整个包的结构可能依赖于连接时协商的 ​能力标志位 (Capability Flags)​​(例如是否启用 SSL、压缩、协议版本等)。
    • 固定值通常用方括号 [ ] 内的十六进制表示(例如 [00])。

总结:​

数据包是理解 MySQL 底层通信协议的基石。它定义了:

  • 数据如何在网络上传输:​​ 被打包成最大 16MB 的块。
  • 包的结构:​​ 4 字节头(长度 + 序列号) + 实际数据。
  • 处理大数据的方法:​​ 分包发送,用满 3 字节长度的 FF FF FF 表示后面还有更多数据块。
  • 保证顺序的机制:​​ 递增的序列号 (sequence_id)。

理解 MySQL Packets 对于进行网络抓包分析、开发 MySQL 客户端/服务器、理解高级特性(如压缩、SSL)如何在此基础协议上运作至关重要。文档中提到的函数(如 my_net_write, net_send_ok)是 MySQL 服务器/客户端内部实现这些协议逻辑的关键部分。