凌晨2点,MySQL连接爆了!我用这招28秒救回90万订单

异常现象:2001个幽灵连接,max_connections早爆了

MySQL官方文档明确说明:ERROR 1040(HY000):Too many connections触发条件是当前连接数超过max_connections参数值。

我们当时的监控数据很明确。

SHOW GLOBAL STATUS LIKE'Threads_connected';显示2001。

SHOW VARIABLES LIKE'max_connections';确认是2000。

应用日志每秒500+条1040错误。架构背景:SpringBoot 2.7+HikariCP 4.0+MySQL 8.0.32,主从架构,18个应用实例,每个实例理论最大连接100个,总容量应该绰绰有余。

但现实是,Sleep连接占总数的82%,这就是幽灵军团。配置合理≠实际稳定,监控数据才是真相。 秒级自救:借管理端口起死回生MySQL8.0.14及以上版本增加了admin_address以及admin_port,默认是33062这个端口,和平常的3306端口完全分开。

这种设计就是,用来让DBA在紧急时候使用,能够避开连接数的限制。完整自救步骤(实测28秒)

  1. 创建临时管理员(权限最小化)

    sql 复制代码
    CREATE USER 'tmp_admin'@'%' IDENTIFIED BY 'Tmp2025!Secure';
    GRANT PROCESS, SUPER, REPLICATION CLIENT ON *.* TO 'tmp_admin'@'%';FLUSH PRIVILEGES;
  2. 管理端口登入

    css 复制代码
    mysql -u tmp_admin -p -h 127.0.0.1 --port=33062 --connect-timeout=5
  3. 验证成功:此时SHOW_PROCESSLIST;能看到所有2001个连接,包括Sleep的。

  4. 数据验证:登录后立即执行SELECT COUNT(*) FROM information_schema.PROCESSLIST WHERE COMMAND='Sleep';确认1640个Sleep连接。

太绝了,8.0的管理端口救了我7次夜间故障。 根因定位:80%的连接在睡眠,sys视图一目了然sys.user_summary_by_statement_type是MySQL8.0sys模式的神器,按语句类型汇总用户连接统计。执行结果(真实截图数据)

statementtype count ratio
sleep 1640 82%
Query 280 14%
Connect 81 4%

继续深挖。

sql 复制代码
SELECT * FROM sys.processlistWHERE state='Sleep' AND time > 300ORDER BY time DESC LIMIT 10;

发现82%的Sleep连接存活超过5分钟,明显是泄漏。80%Sleep连接=连接池配置失控,数据不会说谎。 真正的元凶:maxIdle时间过长+无泄漏检测HikariCP官方推荐:maxLifetime应小于MySQLwait_timeout(默认28800s=8小时),idleTimeout建议5-10分钟。我们之前的配置是灾难。

yaml 复制代码
hikari:  
maximum-pool-size: 100      # 峰值 OK  
minimum-idle: 20           # 偏高  
max-lifetime: 30m          # ❌ 过长!  
idle-timeout: 10m          # ❌ 回收太慢  
leak-detection-threshold: 0 # ❌ 关闭检测!

行业数据对比(阿里云最佳实践)

  • 合理maxIdle:20-50(视QPS)
  • leakDetectionThreshold:3000-10000ms

我们的QPS峰值800,18实例,理论需45个活跃连接即可。

代码隐患:3处JDBC操作缺少try-with-resources,异常路径未释放连接。配置不是越多越好,是越精准越安全。 修复方案:池子瘦身+死信检测双保险上线后出现这种状况,连接数从2001降至峰值58,随后逐步回落至25至35的区间,稳定性提高了16倍。核心改动

makefile 复制代码
spring:  
datasource:    
hikari:      
maximum-pool-size: 80      # ↓20%,匹配实际峰值      
minimum-idle: 10           # ↓50%      
max-lifetime: 5m           # 5分钟强制刷新      
idle-timeout: 300000       # 5分钟回收空闲      
leak-detection-threshold: 5000  # 5秒告警

leakDetectionThreshold原理:连接checkout后超过阈值未return,打印stacktrace定位泄漏代码。修复后日志Connection leak detection triggered for example.com.example.MyService#queryUser,stack trace follows3处代码立即修复,故障率下降94%。预防之道:MySQL8.0.28+连接内存限制MySQL8.0.28新特性:connection_memory_limit,默认每个连接1MB,可设16MB。

超限自动KILL。配置

ini 复制代码
SET PERSIST connection_memory_limit = 16777216;  # 16MBSET PERSIST connection_memory_chunk_limit = 1048576;  # 1MB 递增

实际效果数据

  • 前:单连接峰值内存28MB
  • 后:强制杀掉超限连接,OOM风险降为0
  • 监控:SHOW STATUS LIKE 'Aborted_clients';增加但可控

结合对连接池进行优化,系统的容量提升了3倍,单个实例支持1200QPS。8.0的内存限流=最后的防线,一个参数挡住OOM雪崩。 总结与展望凌晨两点的那次事件,成了团队数据库管理的宝贵经验,从以往的被动应对转为主动监控,我们依靠数据做决策,通过优化配置来保障系统稳定。现在标准流程是:

  1. 连接池参数按QPS计算:maxPoolSize=QPS*1.5连接复用率(0.8)
  2. 强制开启leakDetectionThreshold=5s
  3. MySQL8.0+开启connection_memory_limit=16M
  4. 每周跑sys视图体检

上线90天,类似故障0次,客户满意度回升22%。
技术人的成长,就是从一次次血亏中爬起来。 碰到连接方面的问题的时候,不要着急,先试着操作管理端口,随后查看sys视图,最后调整连接池,你分享的实践经验,是我持续深入钻研技术的最优动力。

声明,此文章里90%是我本人原创,有极少部分素材由AI帮助生成,而且所有内容我都已经认真核查,图片素材要么是真实的要么是AI原创的,此文章旨在传播正能量,不存在低俗不好的引导,期望读者可以理解。

相关推荐
_852 小时前
你真的懂context吗?
后端
总是学不会.2 小时前
【JUC编程】多线程学习大纲
java·后端·开发
BingoGo2 小时前
使用 PHP 和 WebSocket 构建实时聊天应用:完整指南
后端·php
JaguarJack2 小时前
使用 PHP 和 WebSocket 构建实时聊天应用 完整指南
后端·php
CodeSheep3 小时前
中国四大软件外包公司
前端·后端·程序员
千寻技术帮3 小时前
10370_基于Springboot的校园志愿者管理系统
java·spring boot·后端·毕业设计
风象南3 小时前
Spring Boot 中统一同步与异步执行模型
后端
聆风吟º3 小时前
【Spring Boot 报错已解决】彻底解决 “Main method not found in class com.xxx.Application” 报错
java·spring boot·后端
乐茵lin3 小时前
golang中 Context的四大用法
开发语言·后端·学习·golang·编程·大学生·context