MySQL报错OS error 24的根本原因是启动它的shell进程ulimit -n过低,而非MySQL自身配置;必须同步修改limits.conf、systemd服务LimitNOFILE及重启生效。

MySQL备份报错 OS error 24(Too many open files)根本不是MySQL自己开太多文件,而是它启动时继承的 shell 进程句柄上限太低——ulimit -n 没调对,其他所有配置都白搭。
为什么改了 my.cnf 的 open_files_limit 还是没用
MySQL 启动后会尝试把 open_files_limit 设成你配的值,但操作系统会强制截断为启动它的 shell 进程当前的 ulimit -n 值。比如你在 my.cnf 里写 open_files_limit = 65535,但 MySQL 是 systemd 或 root shell 启动的,而那个 shell 的 ulimit -n 是 1024,那最终生效的仍是 1024。
- 查真实生效值:登录 MySQL 执行
SHOW VARIABLES LIKE 'open_files_limit';,看到的才是最终结果 -
open_files_limit是只读变量,无法运行时 SET;修改必须重启 mysqld - 即使
my.cnf配了,如果没配对应用户的limits.conf,systemd 服务也可能忽略它
Linux 下必须同时改三处 ulimit
只改一处大概率失败。顺序和依赖关系很关键:
- 先确认当前用户级限制:
ulimit -n(注意:要以运行 mysqld 的用户身份执行,比如sudo -u mysql bash -c 'ulimit -n') - 修改
/etc/security/limits.conf,加两行(假设 MySQL 由mysql用户运行):mysql soft nofile 65535mysql hard nofile 65535 - 如果用 systemd 管理 mysqld(现代发行版默认),还需覆盖 systemd 默认限制:
创建/etc/systemd/system/mysqld.service.d/limits.conf,内容:[Service] LimitNOFILE=65535
- 改完必须重启 systemd daemon 和 mysqld:
sudo systemctl daemon-reload && sudo systemctl restart mysqld
innodb_open_files 别乱设成和 ulimit 一样大
这个参数控制 InnoDB 缓存多少个 .ibd 文件句柄,但它只是“想开”,不等于“能开”。设太高反而浪费内存、拖慢打开速度,还可能挤占 binlog、socket、临时文件等必需句柄。
- 生产环境建议设为
ulimit -n的 60%~70%,例如ulimit -n是 65535,就设innodb_open_files = 40000 - 不要设成
65535或0(0表示自动推导,但推导逻辑在高表数量下容易失准) - 检查当前值:
SHOW VARIABLES LIKE 'innodb_open_files'; - 该值只影响 InnoDB 表空间打开行为,不影响
mysqldump或xtrabackup自身打开文件的能力——它们直接受 shellulimit约束
Windows 上遇到 Errno 24 要小心注册表 SharedSection
Windows 不走 ulimit,而是靠 GDI/User 对象和 Session 共享内存段限制。备份工具(如 mysqldump.exe)卡住时,重点看注册表项:
- 路径:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems - 修改
Windows字符串值里的SharedSection,例如从1024,20480,768改成1024,20480,2048(第三个数是 per-session desktop heap,影响句柄池大小) - 改完必须重启系统才生效
- 更稳妥的做法是:在批处理中用
start /high提权启动,或直接换用 WSL2 下跑备份脚本(绕过 Windows 句柄模型)
真正容易被忽略的是:xtrabackup 和 mysqldump 这类外部工具,它们不是 MySQL 线程,而是独立进程——它们的文件句柄上限完全取决于自身启动时的 shell 环境,和 MySQL 内部配置毫无关系。调参前,先 ps aux | grep xtrabackup 看它跑在哪个用户下,再查那个用户的 ulimit -n。


















