MySQL 的客户端/服务器通信协议

MySQL 的客户端和服务器之间的通信协议是“半双工”的,这意味着,在任何时刻,要么是由服务器向客户端发送数据,要么是由客户端向服务器发送数据,这两个动作不能同时发生。这种协议让 MySQL 通信变得简单快速,但是也从很多地方限制了 MySQL。一个明显的限制是,这意味着没法进行流量控制,一旦一端开始发送消息,另一端要接收完整个消息才能响应它。

客户端一个单独的数据包将查询传给服务器。一旦客户端发送了请求,它能做的事情就只是等待结果了。

服务器响应给用户的数据通常很多,由多个数据包组成。当服务器开始响应客户端请求时,客户端必须完整地接收整个返回结果,而不能简单地只取前面几条结果,然后让服务器停止发送数据。在这种情况下,客户端若接收完整的结果,然后取前面几条需要的结果,或者接收完几条结果后就“粗暴”地断开连接,都不是好主意。这也是在必要的时候一定要在查询中加上 LIMIT 限制的原因。

连接 MySQL 的库函数

多数连接 MySQL 的库函数都可以:

  • 获得全部结果集并将结果缓存到内存里

  • 逐行获取需要的数据

默认一般是获得全部结果集并将它们缓存到内存中。MySQL 通常需要等所有的数据都已经发送给客户端才能释放这条查询所占用的资源,所以接收全部结果并缓存通常可以减少服务器的压力,让查询能够早点结束、早点释放相应的资源。多数情况下这没什么问题,但是在需要返回一个很大的结果集的时候,这样做并不好,因为库函数会花很多时间和内存来存储所有的结果集。

如果能够尽早开始处理这些结果集,就能大大减少内存的消耗,在这种情况下可以不使用缓存来记录结果而是直接处理。这样做的缺点是,对于服务器来说,需要查询完成后才能释放资源,所以在和客户端交互的整个过程中,服务器的资源都是被这个查询所占用的。

将结果返回给客户端

MySQL 将结果集返回客户端是一个增量且逐步返回的过程。

这样处理有两个好处:

  • 服务器端无须存储太多的结果,也就不会因为要返回太多结果而消耗太多内存

  • 可让 MySQL 客户端第一时间获得返回的结果。

结果集中的每一行都会以一个满足 MySQL 客户端/服务器通信协议的封包发送,再通过 TCP 协议进行传输,在 TCP 传输的过程中,可能对 MySQL 的封包进行缓存,然后批量传输。

最后更新于