真正压垮mysql的不是max_connections数值,而是每个连接消耗的内存;需根据历史峰值(show status like 'max_used_connections')和应用连接池规模(如4×50=200)加30%余量取整到50倍数(如300)设为起步值,同时调高ulimit -n、合理设置线程级buffer(256k~512k)、配置max_user_connections(全局值的20%~30%)。

不能只看 max_connections 数值,真正压垮 MySQL 的从来不是连接数本身,而是每个连接偷偷吃掉的内存。
查历史峰值再定目标值,别信“别人家的配置”
盲目套用 1000、2000 这类数字,90% 会触发 OOM killer 杀掉 mysqld。真实合理值必须基于你自己的业务水位:
- 先执行
SHOW STATUS LIKE 'Max_used_connections';,看过去最高用过多少 - 再核对应用侧连接池总规模:比如 4 台应用服务器 × HikariCP 的
maximumPoolSize = 50,理论峰值是 200,加 30% 余量 ≈ 260 - 取两者较大值,向上取整到 50 的倍数(如 300),作为起步值
- 如果
Max_used_connections长期稳定在 80 以下,说明当前默认 151 已足够,别硬调
同步改 ulimit -n 和线程级 buffer,否则等于白设
max_connections 不是孤立参数。MySQL 启动时会预分配文件描述符(fd),每个连接至少占 1 个 fd,外加日志、表缓存等开销。若系统限制太低,服务根本起不来,或运行中突然崩溃:
- 检查当前限制:
ulimit -n - 要求:
ulimit -n≥max_connections+ 200(留出安全余量) - 永久生效需改
/etc/security/limits.conf,添加:mysql soft nofile 4096mysql hard nofile 4096 - 关键陷阱:
sort_buffer_size、read_buffer_size、join_buffer_size是线程级分配——设成 4MB,300 个连接就吃掉 1.2GB;生产建议显式设为 256K~512K,别让它们悄悄涨到 2M+
必须配 max_user_connections,否则压测直接失败
全局 max_connections 调高了,但账号本身有更严的上限,应用照样连不上:
- 执行
SELECT user, host, max_user_connections FROM mysql.user;查当前用户限制 - 对业务账号执行:
ALTER USER 'app_user'@'%' MAX_USER_CONNECTIONS = 300;(建议设为全局值的 20%~30%) - 注意:
SET GLOBAL max_user_connections = 300;是全局默认值,不作用于已有账号,必须用ALTER USER
最容易被忽略的是:单连接内存消耗不是固定值,它随查询类型动态放大。一个没加 LIMIT 的全表排序,可能瞬间把 sort_buffer_size 拉满并触发磁盘临时表,而这个过程对监控不可见——直到 mysqld 被 OOM killer 杀掉。











