先查lsof -p $(pgrep mysqld) | wc -l得实际打开数,再cat /proc/$(pgrep mysqld)/limits | grep "Max open files"看进程级软硬限制;若前者远小于后者但报错持续,则需检查systemd LimitNOFILE配置、my.cnf中open_files_limit值及是否reload并重启服务。

查清MySQL进程实际打开的文件数和系统限制值
别急着改配置,先确认是不是真卡在上限。用 lsof -p $(pgrep mysqld) | wc -l 统计当前打开的 fd 数;再执行 cat /proc/$(pgrep mysqld)/limits | grep "Max open files" 看内核对这个进程的实际软硬限制。如果前者接近后者(比如 64200 / 65536),说明是系统级瓶颈;如果前者才几百、后者却显示 1024,那大概率是启动环境没继承到新限制。
systemd服务必须显式配LimitNOFILE
MySQL由 systemd 管理时,/etc/security/limits.conf 默认被忽略——这是最常卡住的地方。必须编辑服务单元文件(如 /usr/lib/systemd/system/mysqld.service 或 /etc/systemd/system/mysqld.service),在 [Service] 段下添加:
[Service] LimitNOFILE=65536
然后运行 sudo systemctl daemon-reload,再 sudo systemctl restart mysqld。不 reload、只 restart 不生效;reload 但不 restart 也不生效。
my.cnf里的open_files_limit要留余量
open_files_limit 不是“设多少就用多少”,它是 MySQL 启动时向系统申请的目标值,最终取 min(系统允许最大值, 配置值)。所以建议设为 systemd LimitNOFILE 值的 80%~90%,例如:
- systemd 设了
65536,my.cnf就写open_files_limit = 55000 - 留出空间给 error log、slow log、socket、临时表等其他 fd
- 不能带单位(如
65536k),必须是纯整数 - 设得比系统限制高,MySQL 会静默下调,并在 error log 写 warning,不会中断启动
Docker、phpEnv、XtraBackup场景下的特殊处理
这些场景容易漏掉关键环节:
- Docker 运行 MySQL:必须加
--ulimit nofile=65536:65536到docker run命令里,宿主机的 ulimit 不传递给容器 - phpEnv 环境:检查是否用了自定义 service 文件,且里面没配
LimitNOFILE;也注意 PHP-FPM 和 Nginx 会共用系统 fd 总额 - XtraBackup 报错
InnoDB: Error number 24:它直连 MySQL 文件系统,同样受目标进程(即 mysqld)的 fd 限制约束,不是单独调大 xtrabackup 自身限制就能解决 - MySQL 8.0+ 若启用了
mysqld_safe包装器,它可能覆盖LimitNOFILE,建议禁用mysqld_safe,直接跑原生mysqld
真正生效的关键永远是:systemd 单元文件改了、reloaded、restart 了,且 /proc/PID/limits 和 SHOW VARIABLES LIKE 'open_files_limit' 两个地方数值一致。中间任何一环断开,都会回退到 1024。


















