直接原因是MySQL进程文件描述符限制过低,根本原因是systemd未加载ulimit配置;需查cat /proc/$(pgrep mysqld)/limits确认实际限制,编辑systemd服务文件添加LimitNOFILE=65536,执行daemon-reload并restart。

MySQL启动失败报“Too many open files”怎么办
直接原因是 MySQL 进程实际能打开的文件描述符数(nofile)低于 max_connections 设置值,而根本原因几乎总是 systemd 未正确加载 ulimit 配置。你改了 /etc/security/limits.conf,但 mysqld 是由 systemd 启动的,它压根不读这个文件。
实操建议:
- 先查 MySQL 进程真实生效的限制:
cat /proc/$(pgrep mysqld)/limits | grep "Max open files"—— 看到的数值才是它真正能用的 - 别在 shell 里执行
ulimit -n 65536,这仅影响当前终端,对 mysqld 无效 - 必须编辑
/etc/systemd/system/mysqld.service.d/override.conf,加入:[Service] LimitNOFILE=65536 LimitNPROC=65536
- 执行
systemctl daemon-reload && systemctl restart mysqld,漏掉daemon-reload就白改
为什么改了 limits.conf 还是不生效
因为从内核 2.6.32 起,/etc/security/limits.d/90-nproc.conf 会覆盖 /etc/security/limits.conf 中同名项;而且 PAM 模块只在用户登录时加载 limits,systemd 服务默认绕过 PAM。
常见错误现象:
-
ulimit -n显示 65536,但cat /proc/$(pgrep mysqld)/limits仍显示 1024 - 修改
limits.conf后没重登 SSH,或用了su -而非全新登录(su -不触发pam_limits.so) - 硬限制(
hard nofile)设得比系统级/proc/sys/fs/file-max小,导致设置被截断
验证步骤:
- 运行
ulimit -Hn和ulimit -Sn确认当前会话软硬限制 - 检查系统级上限:
cat /proc/sys/fs/file-max,若小于 131072,需 echo 131072 > /proc/sys/fs/file-max 或写入/etc/sysctl.conf - 确认 PAM 加载:检查
/etc/pam.d/common-session是否含session required pam_limits.so
MySQL max_connections 和 ulimit 的匹配关系
max_connections = 10000 不代表只要开 1 万个连接就完事——每个连接至少占用 1 个文件描述符,加上日志、临时表、socket 监听等,实际需要的 nofile 至少是 max_connections × 1.2,建议留出余量设为 65536。
关键参数差异:
-
max_connections是 MySQL 层面的逻辑连接上限,设在my.cnf的[mysqld]段 -
LimitNOFILE是 systemd 对进程级文件描述符的硬性封顶,优先级高于limits.conf -
fs.file-max是整个系统的总文件句柄池,必须 ≥ 所有服务LimitNOFILE之和
性能影响:
- 若
LimitNOFILE过低,MySQL 在达到限制后会拒绝新连接,报错ERROR 1040: Too many connections,但日志里可能只写Can't create thread或静默丢包 - 盲目调高
max_connections到 20000+ 会导致线程栈内存暴涨,可能触发 OOM killer,反而更不稳定
动态调整 MySQL 进程 limits 而不重启
生产环境不能随便重启 MySQL?可以用 procfs 直接改运行中进程的 limits,绕过配置文件和 reload 流程。
操作方式(需 root):
- 查 mysqld PID:
pgrep mysqld - 临时提高其
nofile上限:echo -n "Max open files=65536:65536" > /proc/$(pgrep mysqld)/limits - 注意:该操作只对当前进程有效,重启后失效;且不能突破
fs.file-max和 systemdLimitNOFILE的硬约束
这个技巧适合应急扩容,比如压测中途发现连接数卡住,但又不能停服务。不过它掩盖了配置缺失问题,上线前仍要补全 systemd override 和内核参数。











