From 79151adb1991abfb48efb0ebb494ea6373010bfa Mon Sep 17 00:00:00 2001 From: fengzhao Date: Fri, 1 Nov 2024 11:52:32 +0800 Subject: [PATCH] mysql docs --- ...23\345\214\205\346\246\202\350\277\260.md" | 87 +++++++++++++++++-- 1 file changed, 81 insertions(+), 6 deletions(-) diff --git "a/docs/foundmental/1.MySQL\345\215\217\350\256\256\345\210\206\346\236\220\344\270\216\346\212\223\345\214\205\346\246\202\350\277\260.md" "b/docs/foundmental/1.MySQL\345\215\217\350\256\256\345\210\206\346\236\220\344\270\216\346\212\223\345\214\205\346\246\202\350\277\260.md" index efb29c478..24453becf 100644 --- "a/docs/foundmental/1.MySQL\345\215\217\350\256\256\345\210\206\346\236\220\344\270\216\346\212\223\345\214\205\346\246\202\350\277\260.md" +++ "b/docs/foundmental/1.MySQL\345\215\217\350\256\256\345\210\206\346\236\220\344\270\216\346\212\223\345\214\205\346\246\202\350\277\260.md" @@ -72,7 +72,32 @@ MySQL 客户端和服务器之间的通信怎么实现?协议特征有哪些 - 错误处理:MySQL 协议支持服务器返回错误信息,包括错误代码和错误描述,以便客户端处理异常情况。 -- 安全连接:MySQL 协议支持通过 SSL/TLS 进行通信加密,保护会话数据的安全性。 +- 安全连接:MySQL 协议支持通过 `SSL/TLS` 进行通信加密,保护会话数据的安全性。 + +- 广泛使用 flag 标记位:在握手阶段的登录请求响应报文中包含了服务端能力flag字段,以及业务通讯中的数据报文中也可以包含服务器状态flag标记位。 + + +#### 数据包格式 + +MySQL的客户端和服务端交互是以数据包(Packet) 为单位进行的, 每个包的大小长度有限制, 最长为 2^24 -1 个字节(即 16MB)。`max_allowed_packet` 表示 MySQL Server 或者客户端接收的 packet 的最大大小,packet 即数据包,MySQL Server 和客户端上都有这个限制。**注意,这里说的数据包大小是指 MySQL 应用层对数据的约定,在网络协议封装中,TCP 层和 IP 层各自都有各自的单个数据报文限制,即 MTU 和 MSS 等**。 + +若包长度过大, 则客户端需要自行将包分片, 使得每段的长度在 MySQL 包的最大长度之下, MySQL Packet 由 Header 和 Body 组成, Header 包含两个字段: 包长度(payload_length)、序列号(sequence_id), Body 则是包的主体部分, 它的长度由 Header 中的 payload_length 字段指示, 包长度字段固定使用 int<3> 类型, 序列号固定使用 int<1> 类型, 当客户端和服务端开始交互时, 由客户端初始化 0 序列号, 之后每次交互, 数据发出方都基于前一个 sequence_id 增一, sequence_id 不是恒定唯一的, 当交互次数足够多后, 它会重新回到 0。 + + + +| 名称 | 数据类型 | 占用空间 | 解析 | | +| ------------------------------- | -------- | -------- | ------ | ---- | +| Packet Length(payload_length) | int<3> | 3byte | 包长 | | +| sequence_id | int<1> | | 包序号 | | +| payload | | | | | + +因为前三个字节最大只能表达16M的长度,这是三个字节表达无符号整型的极限,所以,每次客户端可以接受到的单个最大数据包为16M+4个字节。 + +对于`payload`部分大于等于16MB的,MySQL会将数据进行切分,每16MB为一部分,然后将切分的数据按照数据包的格式封装,进行发送,直到切分的数据部分长度小于16MB。 + + + + @@ -216,6 +241,58 @@ MySQL 连接的方式有多种, 比如 TCP/IPv4、TCP/IPv6、UNIX domain sockets + + +#### 命令执行阶段 + +命令执行阶段在官网文档中,叫 `Command Phase`。在这个阶段,就有点像 HTTP 的请求响应这种一问一答的通信模型。 + +首先,客户端发送一个序号(sequence-id)为0的首包。 + + + +##### 客户端命令请求报文 + +客户端可以发送各种不同类型的命令包,payload中的第一个byte描述`command-type`。这个type在include/my_command.h中以enum_server_command枚举方式定义 + +命令:用于标识当前请求消息的类型,例如切换数据库(0x02)、查询命令(0x03)等。命令值的取值范围及说明如下表(参考MySQL源代码/include/mysql_com.h头文件中的定义。 + + + + +在官网中,把这些类型分为`Text Protocol`,`Utility Commands`,`Prepared Statements`,`Stored Programs` + +其中,最主要的是 `COM_QUERY` 消息报文,这个是最常见的请求消息类型,当用户执行SQL语句时发送该消息。 + + +##### 回包报文 + +常见MySQL返回的报文有`Data Packet`, `OK Packet`, `EOF Packe`t`, 和`ERROR Packet`。回包格式主要取决于查询是否需要返回结果集。 + +对于诸如 `COM_PING`, `IUD Query` 等不需要返回结果集的命令, 以及连接阶段的登录成功。`MySQL server`如果正确执行这个查询, 会返回 OK 报文给 client。 + + + + + +**OK Packet** + +对于OK包,在 `sql/protocol_classic.cc -> net_send_ok()` 函数中定义的数据包结构。[The Payload of an OK Packet](https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_ok_packet.html) + +在5.7.5版本之后,OK Packet也可以用于表示EOF信息,原先的 EOF_Packet被废弃了。 + +- 如果 header = 0x00 并且packer 长度大于7,说明这个包是 OK 数据包 +- 如果 header = 0xFE 并且 packer 长度小于9,说明这个包是 EOF 包 + +如果设置了`CLIENT_PROTOCOL_41`标记位,即MySQL 版本大于4.1。 该数据包包含一个警告计数。 + + + + + + + + ### 协议数据类型 协议数据类型是与语言无关的数据类型, 可以理解为 `wire type`, 它们是网络字节流中的数据类型。 @@ -228,10 +305,6 @@ MySQL 连接的方式有多种, 比如 TCP/IPv4、TCP/IPv6、UNIX domain sockets ### 数据包格式 -MySQL 的客户端和服务端交互是以数据包(Packet) 为单位进行的, 每个包的大小长度有限制, 最长为 2^24 -1 个字节(即 16MB)。`max_allowed_packet` 表示 MySQL Server 或者客户端接收的 packet 的最大大小,packet 即数据包,MySQL Server 和客户端上都有这个限制。**注意,这里说的数据包大小是指 MySQL 应用层对数据的约定,在网络协议封装中,TCP 层和 IP 层各自都有各自的单个数据报文限制,即 MTU 和 MSS 等**。 - -若包长度过大, 则客户端需要自行将包分片, 使得每段的长度在 MySQL 包的最大长度之下, MySQL Packet 由 Header 和 Body 组成, Header 包含两个字段: 包长度(payload_length)、序列号(sequence_id), Body 则是包的主体部分, 它的长度由 Header 中的 payload_length 字段指示, 包长度字段固定使用 int<3> 类型, 序列号固定使用 int<1> 类型, 当客户端和服务端开始交互时, 由客户端初始化 0 序列号, 之后每次交互, 数据发出方都基于前一个 sequence_id 增一, sequence_id 不是恒定唯一的, 当交互次数足够多后, 它会重新回到 0。 - @@ -295,7 +368,9 @@ MySQL 采用的是挑战-响应方式来进行身份认证。由服务端生成 ![alt text](./response_ok.png) -Response OK ,成功响应,这个没什么好说的。 + + +Response OK ,成功响应,这个没什么好说的。返回的核心字段是 Server Status 这些各种 flag 标记位。