“Sending data”状态持续十几秒以上且Time上涨、State不变,基本可排除SQL执行或锁等待,大概率卡在结果集打包或网络发送环节,需结合tcpdump抓包验证是否为网络瓶颈。

怎么看是不是网络传输阶段卡住的
直接看 SHOW PROCESSLIST 里状态为 Sending data 却持续十几秒以上,且 State 列没变、Time 在涨,基本可以排除是SQL执行或锁等待,大概率卡在结果集打包或网络发送环节。这时候如果客户端连接是长连接、应用层没超时重试,就会一直挂在那里等数据传完。
为什么 Sending data 状态不等于“正在查表”
Sending data 是 MySQL 执行器把数据从存储引擎读出来之后、开始往 socket 缓冲区写入结果集时的状态——它包含两个子阶段:数据序列化(格式转换) 和 内核协议栈发送(TCP write)。前者耗 CPU,后者受网络带宽、MTU、TCP窗口大小、客户端接收速度影响。常见诱因包括:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 返回字段太多,比如
SELECT *拉了几十 MB 的 BLOB 或 TEXT - 客户端网络抖动或接收缓冲区太小(如某些 Java JDBC 默认
socket.receiveBuffer只有 8KB) - 主库和从库之间走公网或跨机房链路,但没启用压缩
- MySQL 配置了
net_buffer_length过小(默认 16KB),导致高频小包发送,触发 Nagle 算法阻塞
怎么验证和临时缓解
先用 tcpdump 抓包确认是否真卡在网络层:在 MySQL 服务器上执行 tcpdump -i any port 3306 -w senddata.pcap,复现慢查询,然后用 Wireshark 打开看是否有大量重传、窗口为 0、ACK 延迟等情况。若确认是网络瓶颈,可尝试以下操作:
- 加
SQL_NO_CACHE排除查询缓存干扰(MySQL 5.7+ 已移除,但旧环境仍需注意) - 在连接串里加
useCompression=true(JDBC)或启用mysql_enable_utf8mb4=1同时开启压缩(MySQL 8.0+ 支持zstd压缩) - 调大服务端
net_write_timeout(避免连接被误杀),同时调大客户端 socket timeout - 强制限制结果集大小:
SET SESSION max_allowed_packet = 64*1024*1024;防止单次发送超限触发重试
真正要根治得改 SQL 或架构
网络传输阶段的延迟没法靠调参彻底解决,因为它是结果导向的——你返回的数据越多、越散、越慢,它就越容易卡。最有效的办法永远是:减少单次返回体积。比如把 SELECT * 改成只选必要字段,用分页代替全量拉取,BLOB 字段单独异步加载。如果业务确实需要大批量导出,那就别走实时查询通道,改用 mysqldump + 压缩文件或 CDC 工具同步到对象存储。

















