如何解决MySQL中由于慢SQL占满连接池导致的事务堆积?

阿丽同学_6035

阿丽同学_6035

2026-07-11

770人浏览

原创

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

如何解决mysql中由于慢sql占满连接池导致的事务堆积?

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 阶段(如读取未缓存的数据页),可能还需等待几秒。

MySQL
MySQL

编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。

下载

为什么加了索引,慢查询还是卡在 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 主动探测剔除。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

mysql

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

4303

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

911

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1109

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

6221

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

3063

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

6200

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

8381

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1130

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

992

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL vs MySQL
PostgreSQL vs MySQL

共1课时 | 187人学习