“got timeout reading communication packets”说明连接已建立且认证成功,但服务端读取客户端数据时超时,主因是net_read_timeout过小或网络中断(如lb空闲超时、防火墙断连、snat端口耗尽),需优先抓包验证并检查网络设备,而非调大wait_timeout。

Aborted connection日志里带(Got timeout reading communication packets)怎么查网络问题
这句括号内容是关键线索,说明连接已建立、认证成功,但读取客户端发来的数据时超时了——不是应用没发请求,而是请求卡在半路或根本没发完。优先排查网络层,而不是调大wait_timeout。
-
net_read_timeout默认仅30秒,对跨公网、高延迟链路或慢查询导出极不友好;先用SHOW VARIABLES LIKE 'net_read_timeout';确认值,再结合业务场景判断是否合理 - 抓包验证:在MySQL服务器侧执行
tcpdump -i any port 3306 -w mysql_net_read.pcap,复现问题后过滤重传包(tcp.analysis.retransmission)和零窗口通告(tcp.window_size == 0) - Docker/K8s环境要额外检查:宿主机与容器间iptables规则是否DROP了FIN/ACK、CNI插件是否启用了conntrack老化(默认300秒),这类配置会导致连接“假死”后被MySQL误判为超时
Aborted connection日志里带(Got an error reading communication packets)为什么不是max_allowed_packet问题
虽然这两类错误常被混为一谈,但日志后缀明确写的是“reading”,不是“packet too large”。前者是TCP流中断,后者是MySQL解析SQL时抛出ER_NET_PACKET_TOO_LARGE错误并记录max_allowed_packet相关提示。
- 若
max_allowed_packet过小,典型现象是INSERT/LOAD DATA失败,错误日志中会出现Packets larger than max_allowed_packet字样,且Aborted_clients不会因此增长 - 真正触发
(Got an error reading communication packets)的常见网络原因:中间LB(如AWS ALB)空闲超时设置短于MySQL的net_read_timeout、防火墙主动中断长连接、客户端所在云主机SNAT端口耗尽导致ACK丢包 - 快速验证:用
mysql --protocol=tcp -h $HOST -P 3306 -u $USER -p -e "SELECT SLEEP(45);"模拟长等待,看是否复现该日志;若复现,则基本排除应用代码问题,锁定网络设备或OS参数
如何用performance_schema定位是哪类网络抖动导致Aborted connection
MySQL 5.7+ 的performance_schema.events_statements_summary_by_digest只能看SQL耗时,真正要抓网络异常得靠socket_summary_by_instance和events_waits_summary_global_by_event_name。
- 查异常socket:运行
SELECT * FROM performance_schema.socket_summary_by_instance WHERE COUNT_READ > 0 AND SUM_TIMER_READ = 0 ORDER BY LAST_READ_TIME DESC LIMIT 5;,结果中SUM_TIMER_READ = 0但COUNT_READ > 0说明有读操作发起但未完成,大概率是网络中断 - 查等待事件:执行
SELECT * FROM performance_schema.events_waits_summary_global_by_event_name WHERE EVENT_NAME LIKE 'wait/io/socket/%' AND COUNT_STAR > 1000 ORDER BY SUM_TIMER_WAIT DESC;,重点关注wait/io/socket/sql/client_connection的平均等待时间是否突增 - 注意:这些表默认可能关闭,需提前启用:
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME = 'events_waits_current';
Docker容器内MySQL的Aborted connection为什么查不到真实客户端IP
当MySQL跑在Docker里且使用bridge网络模式时,host字段显示的是容器网桥IP(如172.17.0.1),而非原始客户端IP——这会让网络排查失去目标,误以为是内部服务问题。
- 根本原因是NAT:宿主机iptables做了DNAT,MySQL看到的TCP连接源IP是docker0接口地址,不是客户端真实地址
- 解法一(推荐):改用host网络模式启动容器,MySQL直接监听宿主机端口,
host字段恢复为真实IP - 解法二:在宿主机上用
ss -tuln | grep :3306确认监听地址,再用tcpdump -i eth0 port 3306 and src host $CLIENT_IP在宿主机抓包,绕过容器网络栈 - 隐藏坑:若容器挂载了宿主机
/etc/localtime但未同步时区,wait_timeout计算可能偏差数分钟,导致连接被提前kill——这种时间错位会让网络排查走入歧途
真实网络故障往往藏在日志括号里的那几个单词背后,而不是状态变量涨了多少。抓包和socket统计比调参数更接近真相,但前提是别被容器网络或时区偏移带偏方向。











