合理值应基于历史峰值max_used_connections和应用连接池总规模取较大值后向上取整至50的倍数,如300;必须同步调高ulimit -n≥max_connections+200、严控sort_buffer_size等线程级缓冲参数,并为应用用户配置alter user ... 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 默认值已足够,别硬调。
必须同步改 ulimit 和 my.cnf,否则启动就失败
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 版本重启后会回退。
单连接内存不是固定值,它会被 buffer 参数放大
很多人按“每连接 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 调高了,但账号本身有更严的上限,应用照样连不上:
-
SET GLOBAL max_user_connections = 50对已有用户完全无效——它只影响后续新建用户的默认值; - 正确做法是:
ALTER USER 'app_user'@'%' WITH MAX_USER_CONNECTIONS 50;,主机名必须精确匹配; - 验证是否生效:
SELECT User, Host, max_user_connections FROM mysql.user WHERE User = 'app_user';; - 最关键落地点:你的连接池
maximumPoolSize必须 ≤ 这个值,否则应用启动就报ERROR 1226,不是连接池重试能绕过的。
真正卡住人的从来不是“怎么设”,而是“设完没查 ulimit -n、没核对 buffer 大小、没改用户级限制”。这三个点漏一个,配置就等于白调。











