应修改systemd服务单元的limitnofile为65536并重启mysqld,而非仅改/etc/security/limits.conf;验证需查/proc/pid/limits与show variables双重确认,open_files_limit在my.cnf中应设为limitnofile的80%~90%(如58000),且必须为纯整数。

MySQL报“Too many open files”或“Can't open file: '.\test\mytable.frm' (errno: 24)”怎么办
这不是MySQL配置错了,是Linux给mysqld进程分配的文件描述符(fd)上限太低。哪怕my.cnf里写了open_files_limit = 65535,只要系统层没放开,MySQL启动时就会静默降级到1024,并在错误日志里写Could not increase number of max_open_files to more than 1024。
必须改systemd服务单元的LimitNOFILE,不是/etc/security/limits.conf
systemd管理的MySQL(绝大多数现代发行版默认如此)完全忽略/etc/security/limits.conf。只改那个文件,重启后mysqld进程实际拿到的仍是默认1024。
- 确认是否由systemd管理:
systemctl status mysqld,看Active:行是否为active (running) - 编辑服务单元文件:
/usr/lib/systemd/system/mysqld.service或更推荐用覆盖方式:/etc/systemd/system/mysqld.service.d/override.conf - 在
[Service]段下添加两行:[Service] LimitNOFILE=65536 LimitMEMLOCK=infinity
- 执行
systemctl daemon-reload && systemctl restart mysqld——注意是restart,不是reload
验证open_files_limit是否真生效,别信SHOW VARIABLES alone
SHOW VARIABLES LIKE 'open_files_limit'返回的值可能被MySQL内部逻辑二次计算过(比如按max_connections * 5推导),不代表进程实际能用的上限。真正有效的是内核给进程分配的那个数。
- 查进程当前限制:
cat /proc/$(pgrep -f "mysqld")/limits | grep "Max open files",输出应类似Max open files 65536 65536 files - 再进MySQL执行
SHOW VARIABLES LIKE 'open_files_limit',值应≥65536;若仍为1024或20000,说明systemd没生效或服务没重启 - 如果
open_files_limit设得比系统允许值高,MySQL会自动下调并在错误日志写warning,不会中断启动
open_files_limit在my.cnf里怎么设才不白配
这个参数不是开关,是MySQL启动时向内核申请fd数量的“目标值”。它最终生效值 = min(系统允许最大值, 配置值),所以设太高没用,设太低又卡死。
- 必须是纯整数,不能带单位(如
64k、65535M) - 建议设为systemd中
LimitNOFILE值的80%~90%,例如LimitNOFILE=65536,则open_files_limit = 58000较稳妥 - 顺手加一行
innodb_open_files = 5000(MySQL 8.0+默认已弃用该参数,但老版本仍需显式设) - 别指望靠调大
table_open_cache来绕过fd限制——它反而会加剧fd消耗
最容易被跳过的点:改完systemd配置后忘了daemon-reload,或者以为systemctl reload mysqld就能生效。fd限制是进程启动时一次性继承的,运行中无法热更新。另外,Docker部署的MySQL必须在docker run时加--ulimit nofile=65536:65536,宿主机的设置对容器无效。











