mysql的open-files-limit设了不生效是因为它只是启动时的建议值,实际受限于systemd配置、系统ulimit、用户限制等多层机制;必须通过systemd的limitnofile或mysqld_safe方式设置,且需验证进程级真实限制。

mysql open-files-limit 为什么设了不生效
MySQL 的 open-files-limit 是个“建议值”,不是硬限制,它只在 MySQL 启动时尝试向系统申请对应数量的文件描述符,但能否拿到取决于系统级限制和启动方式。
常见错误现象:mysqld 启动后查 SHOW VARIABLES LIKE 'open_files_limit'; 显示远低于配置值(比如配了 65535,实际只有 5000),或日志里报 Could not increase number of max_open_files to more than XXX。
- systemd 管理的 MySQL(主流发行版默认)会忽略 my.cnf 里的
open-files-limit,必须通过 systemd unit 文件显式设置 - 如果用
sudo service mysql start或直接执行mysqld,可能走的是 root 的 ulimit,而 mysqld 进程实际以mysql用户运行,继承的是该用户的限制 -
open-files-limit在 my.cnf 中必须放在[mysqld]段下,放错位置(如 [client] 或 [mysqld_safe])完全无效
systemd 下正确提升 open-files-limit
Debian/Ubuntu/CentOS 8+ 默认用 systemd,my.cnf 里的 open-files-limit 被无视是常态。必须改 systemd 配置。
实操步骤:
- 运行
systemctl edit mysql(或mariadb,看服务名),创建覆盖片段 - 写入以下内容(注意单位是数值,不是字符串):
[Service] LimitNOFILE=65535
- 保存后执行
systemctl daemon-reload && systemctl restart mysql - 验证:登录 MySQL 执行
SHOW VARIABLES LIKE 'open_files_limit';,同时检查系统级限制:cat /proc/$(pgrep mysqld)/limits | grep "Max open files"
别漏掉:如果 MySQL 是以非 root 用户(如 mysql)运行,还要确认该用户 shell 限制没卡死,比如 /etc/security/limits.conf 里加了 mysql soft nofile 65535 和 mysql hard nofile 65535 —— 但这对 systemd 服务**通常不需要**,除非启用了 PAM 且配置了 limit 模块。
my.cnf 里 open-files-limit 的真实作用场景
它只在两种情况下起效:mysqld_safe 启动,或手动用 mysqld 命令启动且未被 systemd/systemd-sysv-generator 接管。现在几乎只剩开发机或旧部署可能遇到。
配置要点:
- 必须写在
[mysqld]段下,例如:[mysqld] open-files-limit = 65535
- 值不能带单位(不能写
65535K),也不能是表达式 - 它只是“请求值”,MySQL 启动时调用
setrlimit(RLIMIT_NOFILE, ...),失败就默默回退到系统默认值,不会报错中断启动 - 如果同时存在
mysqld_safe包装脚本,它可能自己再设一次 ulimit,优先级高于 my.cnf;此时应改mysqld_safe的启动参数或配置其 own config
查清当前生效的文件描述符限制链路
别只信 SHOW VARIABLES,MySQL 层面的值是结果,不是原因。得顺藤摸瓜:
- 查 MySQL 进程实际限制:
cat /proc/$(pgrep mysqld)/limits | grep "Max open files"—— 这才是真实上限 - 查 systemd 限制:
systemctl show mysql | grep LimitNOFILE - 查 MySQL 配置是否加载:
mysqld --verbose --help | grep "Default options"看 my.cnf 路径,再确认该文件里是否有open-files-limit且位置正确 - 查系统全局限制:
sysctl fs.file-max(内核级总上限),若它小于你设的值,MySQL 根本拿不到
最容易被忽略的是:MySQL 主进程可能有多个线程,每个连接、每个临时表、每个打开的 .ibd 文件都吃 fd,65535 看似很多,但在高并发 + 大量分区表 + 开启 slow log + general log 的场景下,几天就可能耗尽。监控 Aborted_connects 和 Threads_created 异常上升,有时就是 fd 不足的间接信号。











