美文网首页mysql大杂烩网络
MYSQL一次性返回查询结果,还是分批返回?

MYSQL一次性返回查询结果,还是分批返回?

作者: qishuai | 来源:发表于2021-11-24 21:26 被阅读0次

结论:如果结果集大小超过TCP MSS(MAX SEGMENT SIZE),将会分批将结果集返回给客户端。

实验过程如下(除了验证分批传输以外,还有列出和mysql交互过程中的其他抓包):
这里使用的mysql客户端是mycli,您可以自行安装下载。

连接mysql:
mycli -h 10.16.208.21 -P 3321 -u root -p
Password:

以下是连接mysql的抓包过程(还没有输入密码):
可以看到在输入密码之前,mysql server最后发出了FIN,主动断开客户端的连接,感觉应该是为了在没有获取登录权限以前,尽量不占用server资源。


image.png
查询数据:
image.png

No 530: 客户端向mysql server发送查询请求,查询语句如下:

select * from customer_favorite_search limit 100;

No 531-566: mysql server端向客户端分批发送结果集,同时客户端收到消息后,进行ACK确认。

自问自答:

这里需要注意的是,mysql server端每次向客户端发送数据的长度最大为1448,最后一次发送数据的长度941。这里我们可能有些疑问,为什么偏偏是1448,这个数据是怎么确定下来的呢?
原因是这样的:
数据链路层传输的帧大小是有限制的,不能把一个太大的包直接塞给链路层,这个限制被称为「最大传输单元(Maximum Transmission Unit, MTU)」
下图是以太网的帧格式,以太网的帧最小的帧是 64 字节,除去 14 字节头部和 4 字节 CRC 字段,有效荷载最小为 46 字节。最大的帧是 1518 字节,除去 14 字节头部和 4 字节 CRC,有效荷载最大为 1500,这个值就是以太网的 MTU。因此如果传输 100KB 的数据,至少需要 (100 * 1024 / 1500) = 69 个以太网帧。

image.png

参考:https://juejin.cn/book/6844733788681928712/section/6844733788816179207
不同的数据链路层的 MTU 是不同的。通过netstat -i 可以查看网卡的 mtu,如下是我mac电脑的信息:

image.png
回到正题:
1448 = 1500(以太网 MTU) - 20(IP 固定表头大小) - 20(TCP 固定表头大小) - 12(TCP 表头选项)
image.png

从上面的过程,我们可以得出以下结论:

  • mysql server和客户端数据交互采用的是TCP协议
  • 如果结果集大约MTU时,客户端将会分批获取到数据

其实到目前为止,我们没有充分证明,mysql是将结果集一次性返回给客户端的,只能充TCP传输上看,客户端是分批获取到的。
扩展:
mysql的软件架构里面,分配sever层和存储引擎层,server层和存储引擎层的交互是以记录为单位,对于innodb存储引擎层来说,其和存储设备之间是以页为单位进行交互的。innodb引擎按照server层的要求从数据中找到符合条件的,并返回给server层,server层判断是否符合查询要求,如果符合,就将该数据发送到socket缓冲区中,然后继续向innodb引擎要下一条数据,指导第一条数据不满足条件的数据出现。但是socket缓冲区的数据何时发送给客户端,这个时机有操作系统决定,并不再受mysql的控制。
其实流程就是这样的:mysql server判断存储引擎给的数据是否符合查询要求,如果符合就将该条记录发送到socket缓冲区中,如果如何条件的记录有100条,那么server层向socket缓冲区发送数据的过程就有100次,然后由操作系统决定何时将缓冲区的数据发送到对端。

相关文章

网友评论

    本文标题:MYSQL一次性返回查询结果,还是分批返回?

    本文链接:https://www.haomeiwen.com/subject/ifrotrtx.html