mysql启动报“too many open files”需同步配置systemd的limitnofile、内核limits及my.cnf的open_files_limit,否则mysql会静默降级至1024;必须重启服务而非reload,并通过/proc/pid/limits和show variables双重验证实际生效值。

MySQL 启动报 Too many open files 怎么办
直接改系统级文件描述符限制,否则 MySQL 会 silently 降级到 open_files_limit 的低值(常为 1024),哪怕你配置了 65535 也没用。
常见错误现象:MySQL 日志里出现 Could not increase number of max_open_files to more than 1024;SHOW VARIABLES LIKE 'open_files_limit'; 查出来远低于你 my.cnf 里设的值。
- 先确认当前生效的 soft limit:
cat /proc/$(pgrep -f "mysqld")/limits | grep "Max open files" - Linux systemd 管理的 MySQL 必须在 service 单元里显式设置:
LimitNOFILE=65535,不能只靠/etc/security/limits.conf(systemd 会忽略它) - 修改后必须重启 mysqld.service,不是 reload,否则 limit 不生效
my.cnf 里 open_files_limit 设多少才有效
这个参数不是“设了就生效”,它只是 MySQL 启动时向内核申请打开文件数的**目标值**,最终取值是 min(系统允许最大值, 配置值)。
使用场景:当你的表数量多、分区表多、或开了大量临时表/排序缓冲时,实际打开的文件数很容易突破默认值。
-
open_files_limit必须是整数,不能带单位(如 k/M) - 建议设为系统
LimitNOFILE值的 80%~90%,留点余量给 error log、slow log、socket 等其他 fd - 如果设得比系统限制还高,MySQL 会自动下调,并在错误日志写 warning —— 别指望它报错中断
为什么 ulimit -n 改了,MySQL 还是只有 1024
因为 mysqld 进程启动时继承的是 启动它的 shell 的 ulimit,而 systemd 服务默认不读取 /etc/security/limits.conf。
性能影响:fd 不足会导致频繁的文件 close/open,影响表缓存命中率,尤其在高并发小查询场景下,Opened_tables 指标会明显上升。
- 检查 systemd 是否接管:运行
systemctl status mysqld,看 Active line 是否含 “running” - 编辑
/usr/lib/systemd/system/mysqld.service或/etc/systemd/system/mysqld.service.d/override.conf - 加入两行:
LimitNOFILE=65535和LimitMEMLOCK=infinity(后者防因内存锁限制间接影响 fd) - 执行
systemctl daemon-reload && systemctl restart mysqld
验证 open_files_limit 是否真正生效
别只信 my.cnf 里的数字,也别只看 ulimit -n 输出 —— 要查进程实际拿到的值。
容易踩的坑:MySQL 启动后,SHOW VARIABLES LIKE 'open_files_limit' 显示的是它自己“认为”的值,但可能已被内核截断;必须核对 /proc 下真实 limits。
- 查进程号:
pgrep -f "mysqld" - 查真实限制:
cat /proc/<em>PID</em>/limits | grep "Max open files"(注意输出中 soft 和 hard 两个值) - 再查 MySQL 内部值:
mysql -e "SHOW VARIABLES LIKE 'open_files_limit';",两者应基本一致(soft limit 允许有 ±1 差异)
真正卡住的从来不是配置项本身,而是 systemd、内核、MySQL 三层之间对“谁说了算”的静默协商。漏掉任意一层,数值就会在某个环节被悄悄打回原形。










