RDS for MySQL 连接数打满排查实战:从连接统计到参数调优的六步流程

举报
yd_229207802 发表于 2026/11/08 09:34:46 2026/11/08
【摘要】 背景业务高峰期,应用日志突然出现大量 Too many connections,新请求连不上数据库,已建立的连接却还能正常读写。登录 RDS 控制台一看,连接数曲线已经顶到 max_connections 上限。本文记录一次真实的排查过程:先恢复业务,再定位根因,最后把参数和连接池一起调到合理值。需要先建立一个认知:连接数打满不等于并发真的高,很多时候是连接泄漏、慢查询占着连接不放,或者连...

背景

业务高峰期,应用日志突然出现大量 Too many connections,新请求连不上数据库,已建立的连接却还能正常读写。登录 RDS 控制台一看,连接数曲线已经顶到 max_connections 上限。本文记录一次真实的排查过程:先恢复业务,再定位根因,最后把参数和连接池一起调到合理值。

需要先建立一个认知:连接数打满不等于并发真的高,很多时候是连接泄漏、慢查询占着连接不放,或者连接池配得比数据库上限还大。直接调大参数而不找根因,下次高峰还会再打满。

一、确认报错与当前连接数

先确认是不是真的打满,而不是应用侧的偶发超时:

SHOW VARIABLES LIKE 'max_connections';
SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Max_used_connections';

Threads_connected 接近 max_connections,且 Max_used_connections 也接近上限,基本可以确认是连接数打满。同时去云监控服务 CES 看 RDS 实例的连接数曲线,确认打满是从什么时候开始的、是缓慢爬升还是瞬间冲顶——缓慢爬升多半是连接泄漏,瞬间冲顶多半是突发流量或慢查询堆积。

二、按来源分组,看连接都去哪了

SELECT user, host, db, command, COUNT(*) AS cnt, MAX(time) AS max_time
FROM information_schema.processlist
GROUP BY user, host, db, command
ORDER BY cnt DESC;

重点看三类:

  • 某个应用节点(host)的连接数异常高:优先查该节点的连接池配置;
  • 大量 Sleep 状态且 time 很大的连接:空闲连接没有及时释放;
  • 大量 Query 状态且 time 很大的连接:慢查询正在占用连接。

也可以在服务器上快速统计各状态的连接数:

mysql -h <RDS实例内网域名> -P 3306 -u <用户名> -p -e "SHOW PROCESSLIST;" | awk 'NR>1 {print $5}' | sort | uniq -c | sort -rn | head

三、定位占着连接不放的慢查询和长事务

SELECT id, user, host, db, command, time, state, LEFT(info, 100) AS sql_text
FROM information_schema.processlist
WHERE command != 'Sleep' AND time > 10
ORDER BY time DESC;

SELECT trx_id, trx_state, trx_started, trx_mysql_thread_id, trx_query
FROM information_schema.innodb_trx
ORDER BY trx_started;

再结合 RDS 慢日志和 performance_schema.events_statements_summary_by_digest,找到执行次数多、平均耗时长的 SQL。确认无误后,先 KILL 掉明显异常的长查询和长事务持有的连接(执行前和业务方确认,避免误杀正在跑的批量任务):

KILL 12345;

注意:不要直接重启实例。重启会中断所有业务连接,恢复后连接还会重新打满,等于什么都没修。

四、核对应用连接池配置

连接数打满最常见的根因在应用侧。把每个应用实例的连接池上限加起来,和 max_connections 对一下账:

# 以 HikariCP 为例,核对每个应用实例的配置
 grep -r "maximum-pool-size" /path/to/app/config/
 grep -r "minimum-idle" /path/to/app/config/
  • 应用实例数 × 单实例连接池上限,必须小于 max_connections,还要给管理连接、监控和人工排查留 10% 左右的余量;
  • 检查连接泄漏:把连接池的 leakDetectionThreshold 打开后,日志里出现大量连接泄漏告警就是泄漏的证据,常见原因是代码里取了连接没有在 finally 里关闭;
  • 检查超时设置:connectionTimeout、idleTimeout、maxLifetime 配得过长,空闲连接会一直占着名额。

五、应急恢复:先把连接数降下来

  1. KILL 掉 Sleep 时间超过业务阈值(例如 300 秒)的空闲连接;
  2. 临时调大 max_connections 争取恢复时间。RDS for MySQL 的 max_connections 是动态参数,在控制台修改参数组后立即生效,无需重启实例;也可以用有权限的账号临时设置:
SET GLOBAL max_connections = 2000;
  1. 恢复后盯着连接数曲线和应用报错,确认不再继续上涨,再进入下一步。

六、治本:参数、连接池与监控一起调

  • 按内存给 max_connections 定个合理值:每个连接约占用几百 KB 到 1MB 的线程栈和网络缓冲,盲目调到上万只会把内存吃光,一般 8GB 内存的实例配 1000~2000 即可,调大前先算一遍账;
  • 收敛连接池:应用侧按实例数分摊上限,核心服务用独立账号,避免某个服务把连接池打满拖垮其他服务;
  • 治理慢 SQL:慢查询少了,连接占用时间自然变短,这是最有效的“扩容”;
  • 读写分离或代理:读多写少的场景走只读实例,连接压力大的场景可以考虑用数据库代理做连接池复用;
  • 加监控告警:连接数使用率超过 80% 就告警,别等打满了才发现。

小结

连接数打满的排查顺序是:先确认打满,再分组定位来源,然后处理慢查询和长事务,核对连接池,最后才是调参数。调大 max_connections 只是争取时间的应急手段,真正的根因多半在连接泄漏和慢 SQL。把“应用实例数 × 连接池上限 < max_connections”这条账算清楚,再配上 80% 的使用率告警,同样的故障基本不会再来第二次。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。