先查max_connections、Threads_connected、Max_used_connections三值;若后者接近前者且Threads_running极少,说明是Sleep连接堆积而非真实高并发。

别急着改 max_connections,先确认是不是真连满了——用 root 本地 socket 登录,查三件事:max_connections、Threads_connected、Max_used_connections。如果前者是 151,后者接近 150 且 Threads_running 只有 2–3,那基本是 Sleep 连接堆积,不是并发真高。
为什么 SET GLOBAL max_connections 经常不生效
执行完还是旧值?问题不在 MySQL 本身,而在三道硬限制:
-
ulimit -n返回值低于你设的连接数(比如想设 2000,但 ulimit 是 1024),MySQL 启动时会自动向下取整 - systemd 管理的服务必须在
/usr/lib/systemd/system/mysqld.service的[Service]段加LimitNOFILE=65536和LimitNPROC=65536,再systemctl --system daemon-reload && systemctl restart mysqld - MySQL 8.0.22+ 支持
SET PERSIST max_connections = 1000,它写入mysqld-auto.cnf,优先级高于my.cnf;若已用此方式,直接改配置文件也不覆盖
连接池 idleTimeout 和 wait_timeout 必须匹配
多数线上事故根子在应用侧。比如 HikariCP 或 Druid 常见错配:
-
maximumPoolSize(HikariCP)或max-active(Druid)设得比max_connections还高,多个服务一起压就爆 -
wait_timeout设为 300 秒,但连接池的idleTimeout设成 600 秒,连接永远归还不回去 - HikariCP 的
connection-timeout默认 30 秒,网络抖动易堆积;建议调到 10–15 秒,并开leak-detection-threshold
关键原则:idleTimeout 必须严格小于 wait_timeout,否则连接被 MySQL 断掉后,池子还当它活着,下次用就报错。
KILL Sleep 连接只是应急,不是解法
SHOW PROCESSLIST 里看到一堆 Sleep 连接,KILL 掉能抢出几个名额,但几小时后又满——因为泄漏还在继续。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
重点查 USER 和 HOST:
SELECT USER, HOST, COUNT(*) FROM information_schema.PROCESSLIST GROUP BY USER, HOST;
定位异常 IP 或账号。更进一步,结合 information_schema.PROCESSLIST 的 TIME 和 STATE 字段,筛出超时未释放的连接(如 TIME > 300 AND STATE = 'Sleep')。
真正难处理的是连接泄漏本身:它藏在应用代码里,不触发错误,只悄悄吃掉连接数。监控 Max_used_connections 历史峰值比盯瞬时值更有价值,而 wait_timeout 和连接池空闲策略的错位,往往比 max_connections 设小更危险。










