小查询能返回,大查询却挂起或断开,第一反应往往是包大小出了问题。这个直觉通常没错,但几乎总是瞄错了层。三个设置共用“包”这个词,量的却是三件毫不相干的事:数据库驱动程序的传输封装、数据库服务器的消息上限,以及 IP 路径的最大传输单元。调其中一个去修另一个造成的问题,正是五分钟的毛病变成一周调优的原因。下面的顺序花的时间最少。

三个层,一个共用的词

下面每一行都是单位不同、归属也不同的东西,任何一行都不能从其他行推出来。一条数据库消息可以跨越多个 TCP 段和多个 IP 包,所以增大它允许的大小并不会拓宽路径,而调小驱动设置也不等于修改接口的 MTU。这个词出现在三个不同的配置文件里,所以搜索它只会得到三个互不相干的答案。先读错误文本,再决定打开哪个文件。

Setting or observationUnit it describes
SQL Server client network packet settingThe provider's transport packaging for that connection
MySQL communication packet limitA database message, such as one statement, row or replication event
IP path MTUThe largest IP packet the path carries without fragmentation handling

打开配置文件之前,先写下失败的操作属于哪一层。错误文本通常会说明这一点,而这正是人们跳过的那部分。

改设置之前先确认提供程序

对 SQL Server,记录应用、驱动程序或提供程序名称、版本,以及实际生效的连接配置。诊断脚本和桌面应用可以通过不同的提供程序连到同一台服务器,所以对其中一个有效的设置,并不能证明另一个也适用。各提供程序的默认值不同,连接字符串里一个同名字段,也不能证明每个提供程序都同样解释它。

不要仅仅因为旧办法用过某种语法,就把仍在维护的驱动程序换成过时的。现行文档不鼓励在这些较旧组件上做新开发,为了一项设置而继承它们的限制并不划算。

消息被拒不是路径卡死

在 MySQL 8.4 中,通信包文档描述的是:过大的语句、行或二进制日志事件会按适用上限被拒绝,客户端和服务器两边的上限都可能起作用。那是数据库层的拒绝,而不是说网络必须承载一个巨大的 IP 包。读真正的错误和出问题消息的形态:由许多小行组成的大结果,和单独一个超大行是不同情况,失败方式也不同。

MariaDB 安装需要它自己版本所记录的限值和诊断方法。把 MySQL 的默认值照搬到 MariaDB 上,只是多了几步的猜测。

路径证据实际上是什么样子

路径大小问题有自己的指纹:在特定路由和地址族上可复现的、依赖大小的传输失败,其中包含隧道的额外开销,发现反馈也按路径允许的方式表现。单凭超时无法把它和慢查询、驱动缺陷或服务器端上限区分开,而把超时当成 MTU 问题的证据会让你自信地走向错误的层。

如果你确实要测路径,就固定目标、账户和工作负载,让唯一的变量是你正在探测的大小。改了三件事的测试,什么也说明不了哪一件事重要。

只改一个有记录的变量,然后把它记下来

保持目标、账户、提供程序和工作负载不变,记录原始值,只应用一项受支持的改动,并记录结果。让一次测试通过的较小设置,是关于那套被测栈的有用证据;它不是普适最优,也不能确定最初故障的成因。这是两种不同的主张,只有前者能被单次实验支持。

在它自己的层上解决已确认的限值,然后注明那是哪一层。正是这条注记,阻止下一个人因为路径才是问题去调驱动程序。

相关文章