真实合理max_connections值需基于业务水位确定:先查SHOW STATUS LIKE 'Max_used_connections',再核对应用连接池总规模,取较大值并向上取整到50倍数;同时须同步调高系统ulimit -n及配置用户级MAX_USER_CONNECTIONS。

别直接设 max_connections = 1000 或更高——90% 的线上连接耗尽事故,不是连接数不够,而是单连接内存失控 + 系统文件描述符没跟上,最终触发 OOM killer 杀掉 mysqld 进程。
怎么查真实负载再定值
盲目调高只会掩盖连接泄漏或连接池配置错误。真实合理值必须基于你自己的业务水位:
- 先执行
SHOW STATUS LIKE 'Max_used_connections';,看实例启动以来历史最高用过多少连接 - 再核对应用侧连接池总规模:比如 4 台应用服务器 × HikariCP 的
maximumPoolSize = 50,理论峰值是 200,加 30% 余量 ≈ 260 - 取两者较大值,向上取整到 50 的倍数(如 300),作为起步值
- 如果
Max_used_connections长期稳定在 80 以下,说明当前默认值 151 已足够,别硬调
为什么只改 max_connections 一定失败
max_connections 不是孤立参数。MySQL 启动时会预分配文件描述符(fd),每个连接至少占 1 个 fd,外加日志、表缓存等额外开销。若系统限制太低,服务根本起不来,或运行中突然崩溃:
- 检查当前限制:
ulimit -n - 要求:
ulimit -n≥max_connections+ 200(留出安全余量) - 永久生效需改系统级配置:编辑
/etc/security/limits.conf,添加两行:mysql soft nofile 4096mysql hard nofile 4096(假设你设max_connections = 3800) - 然后在
my.cnf的[mysqld]段写死:max_connections = 3800,重启生效 -
SET GLOBAL max_connections = 3800仅临时有效,且某些 MySQL 版本重启后会回退
单连接内存怎么悄悄吃光服务器
很多人按“每连接 256KB”估算内存,结果一上线就 OOM。实际单连接内存 = 基础栈 + 动态 buffer,而后者由多个可调参数决定:
- 关键变量:
sort_buffer_size、read_buffer_size、join_buffer_size、thread_stack - 它们是线程级分配,即每个连接独享一份——设成 4MB,300 个连接就吃掉 1.2GB
- 生产环境建议:除
thread_stack(默认 256KB,够用)外,其他 buffer 类参数保持默认或显式设为 256K~512K - 验证方式:查
SHOW VARIABLES输出,重点盯这几个值,别让它们悄悄涨到 2M+
连接池和用户级限制必须对齐
全局 max_connections 控不住某个账号疯跑脚本或 bug 泄露连接,得用 MAX_USER_CONNECTIONS:
-
ALTER USER 'app_user'@'%' WITH MAX_USER_CONNECTIONS 8——立即生效,不用重启,也不用FLUSH PRIVILEGES - 注意:用户有多个 host(如
'app_user'@'192.168.1.%'和'app_user'@'localhost'),必须分别执行ALTER USER - 设为 0 表示不限制,退回到全局限制,线上账号别留 0
- 验证是否生效不能只看
SHOW GRANTS(它不显示这个值),要查:SELECT User, Host, max_user_connections FROM mysql.user WHERE User = 'app_user' - 应用连接池的
maximumPoolSize必须 ≤ 数据库侧该用户的MAX_USER_CONNECTIONS值,否则第 N+1 个连接会直接被 MySQL 拒绝,报错ERROR 1226 (42000): User 'xxx' has exceeded the 'max_user_connections'
最常被忽略的是:连接数问题往往不是“不够用”,而是“关不掉”。wait_timeout 默认 8 小时,空闲连接长期挂着,Threads_connected 持续走高却不释放——这比数值本身更危险。











