应修改 systemd service 的 limitnofile 参数并重启 mysql 服务,因为 mysql 作为 daemon 进程不受 /etc/security/limits.conf 影响,其文件数限制由启动时继承的 ulimit 决定,需通过 systemctl edit mysql 设置 limitnofile=65536 后 reload 并 restart 才生效。

MySQL 启动报错 Too many open files 怎么办
根本原因是 MySQL 进程打开的文件数超出了系统限制,不是 MySQL 自己配错了,而是它被操作系统卡住了。错误通常出现在 error log 里:Can't open file: 'xxx.frm' (errno: 24) 或启动时直接失败提示 open files limit reached。
关键要分清两层限制:用户级(ulimit -n)和系统级(/proc/sys/fs/file-max),MySQL 只能拿到它启动时所在用户的 ulimit 值,哪怕 file-max 很大也没用。
- 先确认当前 MySQL 进程实际生效的限制:
cat /proc/$(pgrep mysqld)/limits | grep "Max open files" - 别只看 shell 里的
ulimit -n,MySQL 通常是通过 systemd 或 init.d 启动的,它的 ulimit 是独立继承的 - 如果用
systemd,必须在 service 文件里显式设置LimitNOFILE=65536,改 shell 的ulimit完全无效
systemd 下如何永久修改 MySQL 的 ulimit -n
90% 的线上 MySQL 都跑在 systemd 上,但很多人还在 /etc/security/limits.conf 里瞎折腾,那是给 login session 用的,对 daemon 进程基本没影响。
正确做法是覆盖 MySQL 的 systemd unit 配置:
- 运行
sudo systemctl edit mysql(或mariadb,看实际服务名) - 写入:
[Service] LimitNOFILE=65536
- 保存后执行
sudo systemctl daemon-reload && sudo systemctl restart mysql - 重启后立刻验证:
cat /proc/$(pgrep mysqld)/limits | grep "Max open files",确认Soft Limit和Hard Limit都已更新
fs.file-max 和 innodb_open_files 有什么关系
系统级 fs.file-max 是全局总上限,影响所有进程;而 innodb_open_files 是 MySQL 内部缓存表句柄的数量,它不能超过进程级 ulimit,更不能超过 fs.file-max。
常见误解是调大 innodb_open_files 就能解决文件打开问题——其实它只是“想开”,真正“能开”取决于 ulimit 和内核参数。
- 查当前系统上限:
cat /proc/sys/fs/file-max,生产环境建议 ≥ 100000 - 临时调高:
sudo sysctl -w fs.file-max=200000;永久写入/etc/sysctl.conf加一行fs.file-max = 200000 -
innodb_open_files建议设为ulimit -n的 70% 左右(比如 ulimit 是 65536,就设 40000),留余量给 binlog、relay log、socket 等其他文件
为什么改了 limits.conf 还是不生效
因为 MySQL 不是登录用户启动的,它走的是 system slice,不受 /etc/security/limits.conf 管辖。这个文件只对 PAM 认证过的交互式会话有效(比如 ssh 登录后执行命令),对 systemd service、cron、docker 容器全都不起作用。
- CentOS/RHEL 7+ 和 Ubuntu 16.04+ 默认使用 systemd,
limits.conf对服务进程无效是常态,不是配置错误 - 如果非要用 limits.conf,得配合
PAM+systemd-logind,但极其不可靠,且重启后容易丢失 - 最稳妥的方式永远是:systemd service override > /etc/sysctl.conf > /etc/security/limits.conf
真正容易被忽略的是:MySQL 启动后,它的文件句柄限制就固定了,改完配置不重启服务等于白改;而且一定要验证 /proc/PID/limits,别只信配置文件里写了什么。











