直接优化连接参数和查询方式比单纯增加带宽更有效,需同步配置服务端压缩算法、两端max_allowed_packet与net_buffer_length、关闭tcp_slow_start_after_idle,并避免select *及offset分页。

直接改连接参数和查询方式,比单纯加带宽更有效。网络带宽只是瓶颈表象,真正卡住的往往是协议层、传输窗口或结果集本身。
客户端启用压缩协议后仍慢?检查服务端是否同步开启
只在客户端加 useCompression=true 或 --compress 不够——MySQL 8.0+ 要求服务端显式允许压缩算法,否则会静默降级为非压缩传输。
- 服务端必须配置
protocol_compression_algorithms=zlib,zstd(推荐 zstd,压缩比和 CPU 开销更优) - 确认
mysql --version≥ 8.0.18,旧版本不支持 zstd - 连接建立后执行
SELECT @@session.protocol_compression_algorithm;,返回非OFF才算生效 - 如果用的是云数据库(如阿里云 RDS、腾讯云 CDB),部分实例默认禁用压缩,需在控制台打开“网络压缩”开关
大结果集查询反复中断?max_allowed_packet 和 net_buffer_length 必须两端对齐
常见现象是 MySQL server has gone away,但日志里查不到超时或 kill 记录——大概率是某端缓冲区先撑爆了。
- 源库和目标库的
my.cnf都要设:max_allowed_packet = 512M、net_buffer_length = 1M - 客户端命令行也得显式传参:
mysql --max-allowed-packet=512M -h db-host db_name - 如果是 JDBC,URL 里加
&maxAllowedPacket=536870912(单位字节),不能只靠服务端配置 -
net_buffer_length设太大(如 >4M)反而可能触发内核 socket 缓冲区截断,需同步调高net.core.rmem_max
跨机房查询延迟高?绕不开 TCP 内核参数,但别乱调 tcp_slow_start_after_idle
连接池维持的长连接,空闲几十秒后再发查询,吞吐量掉到个位数 KB/s——这不是 MySQL 慢,是 Linux 内核强制重走慢启动。
- 检查当前值:
sysctl net.ipv4.tcp_slow_start_after_idle,Linux 4.1+ 默认为 1 - 生产环境应设为 0:
sysctl -w net.ipv4.tcp_slow_start_after_idle=0,并写入/etc/sysctl.conf - 这个参数只影响已有连接的空闲恢复,不影响新建连接初始拥塞窗口(cwnd)
- 配合调大
tcp_rmem:4096 262144 16777216(万兆内网场景),否则单次 ACK 太小,大量小包拖垮效率
SELECT * 导致网络卡顿?不是带宽问题,是结果集结构失控
一个 SELECT * 返回 10 万行、每行含 3 个 TEXT 字段,实际传输数据可能超 2GB——这已经超出多数应用层处理能力,更别说网络了。
- 永远用明确字段列表代替
*,尤其避开BLOB、JSON、长TEXT - 对大文本字段,用
SUBSTRING(content, 1, 500)截断,或在应用层按需加载 - 分页不用
OFFSET:大数据集下OFFSET 1000000会让服务端扫描 100 万行再丢弃,改用游标(WHERE id > last_id LIMIT 100) - 索引覆盖能直接减少回表,比如
SELECT user_id, status FROM orders WHERE status = 'paid',给(status, user_id)建联合索引,结果全从索引页读出,不碰聚簇索引
最易被忽略的点:很多“网络慢”其实是服务端没响应,而不是传输慢。先用 SHOW PROCESSLIST 看查询状态是不是 Sending data 卡住,还是 Locked 或 Copying to tmp table——前者才真跟网络有关,后者得去查锁或排序逻辑。











