错误分两类:Lost connection at handshake需查网络、MySQL监听和DNS;Lost connection during query才查超时参数、max_allowed_packet及中间设备超时。

直接看错误发生的阶段:如果是 Lost connection at handshake,问题一定在连接建立前;如果是 Lost connection during query,才需要查查询执行、超时或中间设备。
先确认是握手失败还是查询中途断连
这两个错误看着像,但排查路径完全相反。别一上来就改 wait_timeout——它对握手失败毫无作用。
-
Lost connection at handshake表示 TCP 三次握手成功后,MySQL 服务端没发初始认证包(handshake packet),连接在应用层就断了 -
Lost connection during query表示连接已建立、查询已开始执行,但在返回结果途中中断,这时才要看net_read_timeout、max_allowed_packet或中间网关 - 用
tcpdump -i any port 3306 -c 20抓包验证:如果只看到 SYN → SYN-ACK → ACK,没后续 MySQL 协议数据,就是握手失败;如果看到大量ACK后突然出现RST,且时间点贴近查询执行末尾,才是during query
握手失败必须立刻检查的三件事
90% 的 at handshake 问题出在这三层,按顺序查能省下大把时间。
- 用
telnet mysql-server-ip 3306测试:秒断?说明防火墙/安全组没放行 3306 入方向,或 MySQL 根本没监听该 IP - 在 MySQL 服务器上跑
netstat -tulnp | grep :3306:输出为空?说明mysqld没启动,或my.cnf中bind-address写成了127.0.0.1(只允许本地连) - 查
SHOW GLOBAL STATUS LIKE 'Aborted_connects':这个值持续上涨,且错误日志里有reading authorization packet,基本锁定是connect_timeout太小或客户端 DNS 解析卡住(此时加skip-name-resolve)
查询中途断连重点盯这四个参数
不是所有 timeout 都管用,得看谁在哪个环节起作用。
-
wait_timeout:只影响非交互式连接(JDBC、PyMySQL 等),默认 28800 秒。它不控制查询执行时间,只管“空闲多久断” -
net_read_timeout:真正管“读取客户端数据”的超时,比如客户端发了一条大 SQL,服务端等它发完却等不到,就会断。默认仅 30 秒,长事务或大 INSERT 容易踩坑 -
max_allowed_packet:如果报错带Got a packet bigger than 'max_allowed_packet' bytes,说明 SQL 或返回结果超限。设太小会静默断连,建议至少 64M - 云环境必须查 NAT 网关 / SLB 的空闲超时:阿里云 SLB 默认 300 秒,腾讯云 CLB 默认 600 秒——它比 MySQL 的
wait_timeout更早动手,且不发任何提示
连接池配置和 MySQL timeout 必须对齐
很多团队改了 MySQL 的 wait_timeout 还是断,是因为连接池根本没用上这个值。
- HikariCP 的
idle-timeout如果设为 30 分钟,而 MySQL 的wait_timeout是 8 小时,那空闲连接 30 分钟后就被池子自己回收,跟 MySQL 无关 - 但如果
idle-timeout设成 9 小时,而wait_timeout是 8 小时,连接在第 8 小时 1 分钟被 MySQL kill,下次复用就抛Communications link failure - 正确做法:
idle-timeout=wait_timeout- 60,留出缓冲;同时 JDBC URL 加&socketTimeout=30000控制单次读写上限,避免卡死
最常被忽略的是中间设备——你调好了 MySQL 和应用两端,却忘了负载均衡器或防火墙在背后默默掐断连接。只要涉及跨机房、跨云、NAT 场景,第一步就该去翻它的空闲超时文档。


















