mysql的open_files_limit需同步对齐内核fs.file-max、systemd limitnofile和my.cnf中open_files_limit三层限制,缺一即降级至1024;必须重启服务并用/proc/pid/limits与show variables双重验证。

MySQL 的 open_files_limit 不是设了就生效,必须和系统层的文件句柄限制对齐,否则它会静默降级到 1024 —— 这是绝大多数“Too many open files”启动失败或运行时报错的根源。
为什么 SHOW VARIABLES 显示的值远低于 my.cnf 里配置的?
MySQL 启动时向内核申请文件句柄数,最终取值是 min(系统允许最大值, 配置值)。如果系统层没放开,open_files_limit 就只是个愿望值。
- 查进程实际拿到的限制:
cat /proc/$(pgrep mysqld)/limits | grep "Max open files"—— 这才是真实生效值 - 查 systemd 服务继承的限制:
systemctl show mysqld | grep LimitNOFILE,不是ulimit -n当前终端的值 - 常见现象:my.cnf 写了
open_files_limit = 65535,但日志里出现Could not increase number of max_open_files to more than 1024
systemd 下必须改 service 单元,/etc/security/limits.conf 无效
现代 Linux(CentOS 7+/Ubuntu 16.04+)用 systemd 管理 MySQL,它默认不读 /etc/security/limits.conf,哪怕你给 mysql 用户配了 nofile 也没用。
- 创建覆盖配置:
sudo mkdir -p /etc/systemd/system/mysqld.service.d - 写入
/etc/systemd/system/mysqld.service.d/limits.conf:[Service] LimitNOFILE=65535
- 重载并重启:
sudo systemctl daemon-reload && sudo systemctl restart mysqld - 验证是否加载:
systemctl show mysqld | grep LimitNOFILE,输出应为LimitNOFILE=65535 - 别用
infinity:某些内核版本 fallback 到 4096,老老实实填整数
my.cnf 里怎么设 open_files_limit 才有效?
这个参数不是“上限”,而是 MySQL 启动时向系统申请的目标值。设太高会被截断,设太低会拖累 table_open_cache 和连接能力。
- 在
[mysqld]段添加:open_files_limit = 65535(必须是整数,不能带k或M) - 建议设为 systemd
LimitNOFILE值的 80%~90%,留余量给 error log、slow log、socket 等 - 同步控制 InnoDB 行为:
innodb_open_files = 2000(避免单表 .ibd 文件挤占全部 fd) - 检查硬约束:
open_files_limit必须 ≥max_connections * 5或max_connections + table_open_cache * 2,取大者
调完必须重启,且要双重验证
reload 不生效,必须 full restart;而且不能只信配置文件或 SQL 查询结果。
- 重启后立刻查进程限制:
cat /proc/$(pgrep mysqld)/limits | grep "Max open files" - 再查 MySQL 实际采用值:
mysql -e "SHOW VARIABLES LIKE 'open_files_limit';" - 如果两者不一致,说明系统层没对齐 —— 回头重点查 systemd
LimitNOFILE和内核fs.file-max - 注意:MySQL 会根据
max_connections和table_open_cache自动估算最低需求,若open_files_limit太小,它可能反过来压低这两个参数
真正麻烦的不是改哪几行配置,而是三层限制(内核 fs.file-max → systemd LimitNOFILE → MySQL open_files_limit)必须全部对齐,漏一层就会降级到 1024,而错误日志里往往只报“Can't open file”,不会告诉你哪层掉了链子。











