先查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、XtraBackup等场景下的特殊处理
这些场景容易漏掉关键环节:
- Docker 运行 MySQL:必须加
--ulimit nofile=65536:65536到docker run命令里,宿主机的 ulimit 不传递给容器 - XtraBackup 报错
InnoDB: Error number 24:它直连 MySQL 文件系统,同样受目标进程(即mysqld)的 fd 限制约束,不是单独调大xtrabackup自身限制就能解决 - MySQL 8.0+ 若启用了
mysqld_safe包装器,它可能覆盖LimitNOFILE,建议禁用mysqld_safe,直接跑原生mysqld
真正生效的关节点永远是:进程启动那一刻继承的限制值,而不是你后来在 shell 里 ulimit -n 临时改的数字。


















