max_connections 设置过低会导致连接被拒绝、error 1040 频发、应用偶发请求失败或超时、连接池获取连接超时等现象,且 threads_connected 接近上限、threads_created 持续上升。

max_connections 设置过低会导致什么现象
连接被拒绝是直接表现,ERROR 1040 (HY000): Too many connections 会频繁出现,应用端表现为偶发性数据库请求失败、超时或重试激增。尤其在流量突增、连接池未合理配置的场景下,哪怕 QPS 不高,也会因连接复用率低而迅速打满上限。
- 应用日志里反复出现
Connection refused或Can't connect to MySQL server,但 MySQL 进程本身正常 - 监控中
Threads_connected长期接近max_connections,且Threads_created持续上升(说明频繁新建连接) - 连接池(如 HikariCP、Druid)报
Connection acquisition timeout,而非 SQL 执行慢
怎么估算合理的 max_connections 值
不能只看峰值 QPS,得拆开算:每个业务线平均并发连接数 × 连接池最大值 × 安全冗余系数。重点不是“最多能撑多少”,而是“多数时候够不够稳”。
- 先查当前负载:
SHOW STATUS LIKE 'Threads_connected';和SHOW STATUS LIKE 'Threads_created';观察一天内波峰波谷 - 确认各服务连接池配置:比如 Spring Boot 应用设了
maximum-pool-size: 20,共 5 个实例 → 理论上限是 100,再加 30% 冗余 ≈ 130 - 留出系统保留连接:MySQL 自身需要约 10–20 个连接给复制线程、后台任务等,别全分给业务
- 物理内存是硬约束:每个连接约占用 2–4MB 内存(取决于
sort_buffer_size、read_buffer_size等),1000 连接可能吃掉 3GB+,超了会触发 OOM killer
修改 max_connections 后为什么没生效
改了配置文件不等于 MySQL 重启后自动加载,更常见的是被运行时动态值覆盖,或权限/语法细节踩坑。
- 检查是否改对了位置:MySQL 8.0+ 的
my.cnf中必须放在[mysqld]段下,写到[client]或全局段无效 - 确认是否动态生效:
SET GLOBAL max_connections = 500;可临时生效,但 MySQL 重启就还原;持久化必须改配置文件并重启 - 用户权限不足时,
SET GLOBAL会报错ERROR 1227 (42501): Access denied,需有SUPER或SYSTEM_VARIABLES_ADMIN权限 - 某些云数据库(如阿里云 RDS、AWS RDS)禁止修改该参数,只能通过控制台调整“连接数规格”,底层不暴露
my.cnf
连接数调太高反而拖慢性能的几个信号
不是越大越好。连接数膨胀会放大锁竞争、上下文切换开销和内存压力,尤其在高并发短连接场景下,性能可能断崖式下跌。
-
SHOW PROCESSLIST里大量Sleep状态连接长期不释放,说明应用没正确 close 或连接池泄漏 - 系统
vmstat显示cs(context switch)值飙升,CPU 花在调度上远多于执行 SQL - InnoDB 状态里
innodb_row_lock_waits和innodb_mutex_spin_waits显著上升,说明内核锁争用加剧 - 慢查询日志中出现大量
Waiting for table metadata lock或Waiting for global read lock,本质是连接堆积引发元数据锁阻塞链
wait_timeout 和 interactive_timeout 设得过大(比如 28800 秒),会让空闲连接僵死在那占名额。建议设为 300–600 秒,并确保应用层连接池开启 testOnBorrow 或 validationQuery。











