应立即定位并终止慢sql:运行select * from information_schema.processlist where command = 'query' and time > 10 order by time desc limit 10,结合explain分析执行计划、补全缺失索引、限流或下线问题接口,避免单纯kill后迅速复现。

SHOW PROCESSLIST 里大量 Query 状态且 Time > 10s 怎么办
这不是连接池配置低,而是慢 SQL 正在把连接“焊死”在执行中。每个 Query 状态线程都独占一个连接,直到 SQL 执行完或被中断——它不释放,新事务就拿不到连接,COMMIT 和 BEGIN 全部排队失败。
先快速定位:运行 SELECT * FROM information_schema.processlist WHERE Command = 'Query' AND Time > 10 ORDER BY Time DESC LIMIT 10;。重点关注 Info 列(SQL 片段)和 db 列(库名),确认是否集中在某张表或某个业务模块。
- 如果
Info显示INSERT INTO order_log SELECT ...且表行数超千万,大概率是没走索引的全表扫描 - 如果出现
JOIN、GROUP BY或ORDER BY且没命中索引,State常为Creating sort index或Copying to tmp table - 若多条记录
User相同、Host是同一应用 IP,说明该服务批量发起同类慢查询
kill 连接后又迅速堆积?说明没堵住源头
单纯 KILL 只是清缓存,不是修水管。只要上游还在发同样的慢 SQL,1 分钟内连接数就会重回峰值。必须同步做三件事:
- 立刻在应用侧限流或临时下线触发该 SQL 的接口(比如批量导出、报表生成)
- 用
EXPLAIN FORMAT=TREE重跑问题 SQL,确认是否走了索引、是否用了临时表、是否进行了文件排序 - 检查该 SQL 涉及字段是否有缺失索引,特别是
WHERE条件中的组合字段、ORDER BY字段、JOIN关联字段 - 若涉及大表分页(如
LIMIT 100000, 20),改用游标分页或延迟关联
注意:KILL 对正在执行的 SQL 是异步中断,不会立即生效;若 SQL 已进入磁盘 IO 阶段(如读取未缓存的数据页),可能还需等待几秒。
为什么加了索引,慢查询还是卡在 Sending data?
Sending data 不代表网络传输,而是 MySQL 正在向客户端“组织并发送结果集”。如果结果集太大(比如没加 LIMIT 的 SELECT * 扫描千万行),即使有索引,也会因构造结果耗尽内存或打满磁盘 IO,导致连接长时间挂起。
- 查
information_schema.PROCESSLIST中对应连接的Info,确认是否漏写了LIMIT或WHERE - 用
SHOW ENGINE INNODB STATUS\G查看TRANSACTIONS部分,确认事务是否在等锁或刷脏页 - 检查
innodb_buffer_pool_size是否过小——若缓冲池远小于数据量,每次查询都在反复读磁盘,Sending data时间自然飙升 - 监控
Innodb_buffer_pool_reads和Innodb_buffer_pool_read_requests比值,超过 1% 就说明缓冲池严重不足
HikariCP active=80 idle=0 但 SHOW PROCESSLIST 没看到那么多 Query?
这说明连接池里的连接正被应用层“持有”,但还没发 SQL 到数据库——常见于事务开启后,在 Java 层调用 HTTP、RPC 或循环处理数据,导致连接迟迟不提交也不释放。
- 启用 HikariCP 的
leak-detection-threshold=60000(毫秒),日志里会打出未归还连接的堆栈 - 检查代码里是否有
@Transactional方法里嵌套了耗时外部调用,或手动connection.setAutoCommit(false)后忘了commit() - 用
SHOW PROCESSLIST看Command是Sleep但Time很高(如 > 300),基本可判定是应用拿了连接不放,而非 SQL 慢 - 对比
Threads_connected和连接池maximum-pool-size:若前者明显小于后者,说明连接池配置虚高,应用根本用不完,应下调避免资源浪费
真正棘手的是那种“半死不活”的连接:既不在执行 SQL,也没被应用释放,State 是空或 NULL,Time 却持续增长——这种往往卡在 JDBC 驱动内部或网络中间件,得靠连接池的 validation-timeout 和 keepalive-time 主动探测剔除。











