确认MySQL实际读取的配置文件需执行mysql --help | grep "Default options"或SELECT @@global.config_file;,修改必须在[mysqld]段内;设2000却显示214是因ulimit -n过小触发自动降级,需同步调高LimitNOFILE、nofile及max_connections。

改 max_connections 不生效,八成不是参数写错了,而是系统级限制卡死、配置文件没落对地方、或连接本身堆在 Sleep 状态没释放。
怎么确认 MySQL 实际读的是哪个 my.cnf?
MySQL 8.0 启动时会按固定顺序扫描多个路径,改错文件等于白改。常见陷阱是:你在宝塔面板里改了 /www/server/mysql/etc/my.cnf,但 mysqld 实际加载的是 /etc/my.cnf。
- 执行
mysql --help | grep "Default options",看输出里列出的配置文件路径(注意顺序,前面的优先) - 或者查错误日志:
grep "my.cnf" /www/server/data/*.err(宝塔环境) - MySQL 8.0+ 还可直接查:
SELECT @@global.config_file;(需有 FILE 权限) - 确认后,只在真正被读取的那个文件的
[mysqld]段内加max_connections = 1000,别写在[client]或段外
为什么设了 2000 却显示 214?
这是 systemd 服务默认资源限制导致的典型降级行为。MySQL 启动时发现系统 ulimit -n 太小,会自动把 max_connections 往下调,直到满足“每个连接至少一个文件描述符”这个硬约束。
- 先查当前限制:
cat /proc/$(pgrep mysqld)/limits | grep "Max open files",soft limit 必须 ≥ 你设的max_connections - 编辑
/etc/security/limits.conf,加两行:mysql soft nofile 65535mysql hard nofile 65535 - 如果是 systemd 管理(CentOS 7+/Ubuntu 16.04+),还要建
/etc/systemd/system/mysqld.service.d/override.conf,内容为:[Service]LimitNOFILE=65535LimitNPROC=65535 - 改完必须执行:
systemctl daemon-reload && systemctl restart mysqld,systemctl reload不生效
设多大才安全?别只看数字,要看内存和 Threads_running
max_connections 不是并发能力开关,而是内存水位线。每个连接基础开销约 256KB~1MB,设太高会吃光内存;设太低又直接报 ERROR 1040: Too many connections。
- 查真实压力:
SHOW GLOBAL STATUS LIKE 'Max_used_connections';(历史峰值)
再对比SHOW VARIABLES LIKE 'max_connections';,比值长期 > 0.9 就该调了; - 更关键的是
SHOW GLOBAL STATUS LIKE 'Threads_running';——这才是真正在干活的线程数,通常几十个,和总连接数无关 - 内存估算:16GB 服务器,保守按每连接 4MB 算,硬上限约 4000,但线上稳态建议从 300–500 起步,观察 1–2 天监控再微调
- 别忘了同步调
wait_timeout = 300(单位秒),默认 28800 秒(8 小时)会让空闲连接长期占坑,应用层也得配好连接池(如 HikariCP 的maximumPoolSize)
临时改和永久改,哪种更适合生产?
临时改用 SET GLOBAL max_connections = 1000;,命令一敲就生效,但 MySQL 重启就回滚。它适合快速验证是否真缺连接数,但不能替代配置文件落地。
- 生产环境必须走配置文件 + 重启:改完
[mysqld]段,systemctl restart mysqld - 测试环境可先动态试水,确认无异常(比如没触发 OOM、没拖慢响应)再固化
- 注意:
max_connections硬上限是 16384,设成 20000 会被 MySQL 自动截断 - Group Replication 内部会话从 MySQL 8.0.19 起不计入
max_connections,但普通客户端连接仍受限制
真正卡住高并发的,往往不是 max_connections 数字本身,而是 wait_timeout 太大、应用没启用连接池、或系统级文件描述符没放开——这些点漏掉任何一个,调到 5000 也照样报错。


















