小查询能通,大查询失败:到底是哪个包大小?
SQL Server 驱动程序的包、MySQL 的消息上限和 IP 路径的 MTU 是三种不同的单位。依赖大小的故障并不能让它们互换。
小查询能返回,大查询却挂起或断开,第一反应往往是包大小出了问题。这个直觉通常没错,但几乎总是瞄错了层。三个设置共用“包”这个词,量的却是三件毫不相干的事:数据库驱动程序的传输封装、数据库服务器的消息上限,以及 IP 路径的最大传输单元。调其中一个去修另一个造成的问题,正是五分钟的毛病变成一周调优的原因。下面的顺序花的时间最少。
三个层,一个共用的词
下面每一行都是单位不同、归属也不同的东西,任何一行都不能从其他行推出来。一条数据库消息可以跨越多个 TCP 段和多个 IP 包,所以增大它允许的大小并不会拓宽路径,而调小驱动设置也不等于修改接口的 MTU。这个词出现在三个不同的配置文件里,所以搜索它只会得到三个互不相干的答案。先读错误文本,再决定打开哪个文件。
| Setting or observation | Unit it describes |
|---|---|
| SQL Server client network packet setting | The provider's transport packaging for that connection |
| MySQL communication packet limit | A database message, such as one statement, row or replication event |
| IP path MTU | The largest IP packet the path carries without fragmentation handling |
打开配置文件之前,先写下失败的操作属于哪一层。错误文本通常会说明这一点,而这正是人们跳过的那部分。
改设置之前先确认提供程序
对 SQL Server,记录应用、驱动程序或提供程序名称、版本,以及实际生效的连接配置。诊断脚本和桌面应用可以通过不同的提供程序连到同一台服务器,所以对其中一个有效的设置,并不能证明另一个也适用。各提供程序的默认值不同,连接字符串里一个同名字段,也不能证明每个提供程序都同样解释它。
不要仅仅因为旧办法用过某种语法,就把仍在维护的驱动程序换成过时的。现行文档不鼓励在这些较旧组件上做新开发,为了一项设置而继承它们的限制并不划算。
消息被拒不是路径卡死
在 MySQL 8.4 中,通信包文档描述的是:过大的语句、行或二进制日志事件会按适用上限被拒绝,客户端和服务器两边的上限都可能起作用。那是数据库层的拒绝,而不是说网络必须承载一个巨大的 IP 包。读真正的错误和出问题消息的形态:由许多小行组成的大结果,和单独一个超大行是不同情况,失败方式也不同。
MariaDB 安装需要它自己版本所记录的限值和诊断方法。把 MySQL 的默认值照搬到 MariaDB 上,只是多了几步的猜测。
路径证据实际上是什么样子
路径大小问题有自己的指纹:在特定路由和地址族上可复现的、依赖大小的传输失败,其中包含隧道的额外开销,发现反馈也按路径允许的方式表现。单凭超时无法把它和慢查询、驱动缺陷或服务器端上限区分开,而把超时当成 MTU 问题的证据会让你自信地走向错误的层。
如果你确实要测路径,就固定目标、账户和工作负载,让唯一的变量是你正在探测的大小。改了三件事的测试,什么也说明不了哪一件事重要。
只改一个有记录的变量,然后把它记下来
保持目标、账户、提供程序和工作负载不变,记录原始值,只应用一项受支持的改动,并记录结果。让一次测试通过的较小设置,是关于那套被测栈的有用证据;它不是普适最优,也不能确定最初故障的成因。这是两种不同的主张,只有前者能被单次实验支持。
在它自己的层上解决已确认的限值,然后注明那是哪一层。正是这条注记,阻止下一个人因为路径才是问题去调驱动程序。