慢查询日志中Query_time短但应用超时,是因为日志仅记录SQL执行器阶段耗时,不包含连接建立、锁等待(Lock_time需显式开启才记录)、网络IO、客户端解析及GC等环节;根本问题常在锁阻塞、网络超时或客户端处理瓶颈。

慢查询日志里某条SQL显示 Query_time: 0.001234,但应用端报 MySQL server has gone away 或直接卡在 execute() 超时——这不是日志骗人,而是日志只记录「SQL执行阶段」耗时,完全不包含连接建立、网络传输、锁等待、客户端阻塞等环节。问题根本不在SQL本身,而在它前后的时间黑洞里。
为什么慢日志里SQL很快,但应用却超时
MySQL慢查询日志只在SQL真正进入执行器(Executor)后开始计时,到结果集全部返回给服务器内存缓冲区为止。它不统计以下关键耗时:
- 客户端发起请求到TCP连接建立完成(受
connect_timeout控制) - SQL到达服务端后排队等待锁(如行锁、MDL锁),这部分计入
Lock_time,但默认不写入日志,除非显式开启log_slow_verbosity=full - 结果集从InnoDB buffer pool读取后,拼装成网络包发往客户端的网络IO时间(受
net_write_timeout影响) - 客户端接收大量结果后解析、反序列化、GC停顿等应用层耗时(日志完全不可见)
查锁等待和隐式阻塞:看 SHOW PROCESSLIST 和 INFORMATION_SCHEMA.INNODB_TRX
如果SQL在慢日志里快,但实际调用总卡住,大概率是被别的事务堵住了。别只盯着慢日志,立刻查实时状态:
- 运行
SHOW PROCESSLIST,重点看状态列:Waiting for table metadata lock、Locked、Updating后长时间不动,说明卡在锁上 - 执行
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX ORDER BY trx_started DESC LIMIT 5,看是否有长时间未提交的事务(trx_started早于当前时间几分钟以上) - 关联查锁等待:
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS(有结果就说明存在活跃阻塞链) - 注意:这些信息是瞬态的,要抓就得快;生产环境建议配合
pt-deadlock-logger持续捕获
检查客户端与网络层超时配置是否打架
应用端设了 30 秒超时,MySQL 却在 2 秒内返回结果——看似合理,但中间可能被中间件截断:
- 确认应用使用的驱动是否启用了
socketTimeout(JDBC)或connect_timeout/read_timeout(Python MySQLdb/PyMySQL)——这些值必须 > MySQL 的wait_timeout和net_read_timeout - 查负载均衡器(如 Nginx、HAProxy)或云厂商 SLB 的空闲超时,默认常为 60 秒,但有些设成 30 秒甚至 5 秒;它会在 MySQL 返回前就主动断连,导致客户端收到 RST 而非正常响应
- 用
tcpdump抓包验证:如果客户端发完 query 后,没等到 MySQL 的 FIN/ACK,而是先收到对方的 RST 包,基本就是中间网络设备切断了 - Linux 内核参数
net.ipv4.tcp_keepalive_time默认 7200 秒,若中间设备 keepalive 间隔更短(如 60 秒),且没开 TCP keepalive,长连接会静默断开
别忽略客户端侧的“假超时”:结果集太大或 GC 停顿
日志里 Query_time 是 0.02 秒,但应用卡 15 秒才返回——很可能 SQL 执行完,数据还在路上,或卡在应用自己手里:
- 查该 SQL 返回行数:
Rows_examined和Rows_sent(慢日志里有)。如果Rows_sent是几十万,而应用用fetchall()一次性拉,Java 可能触发 Full GC,Python 可能因内存分配卡住 - JDBC 驱动默认启用
useCursorFetch=true时,大结果集会分批拉取,但若没显式设置fetchSize,仍可能一次全载入内存 - 用
EXPLAIN FORMAT=JSON看query_cost和rows估算结果集大小,再比对应用实际处理逻辑 - 加 JVM 参数
-XX:+PrintGCDetails或 Python 的tracemalloc,确认是否真卡在 GC 或对象构造上
真正难排查的不是慢 SQL,而是那些“执行快但整体慢”的调用——它们藏在连接、锁、网络、客户端四层之间,每层都可能悄悄吃掉几秒。日志只是切片,不是全程录像。动手前先明确:你是在查数据库,还是在查整个请求链路?


















