必须修改systemd服务的limitnofile参数并重启mysql,否则仅改my.cnf中open_files_limit无效;需通过cat /proc/$(pgrep mysqld)/limits验证实际生效值。

直接改 my.cnf 里的 open_files_limit 基本无效——它只是 MySQL 启动时的“申请值”,真正卡住的是 Linux 进程级文件描述符限制,必须从 systemd 层下手。
查清 mysqld 进程实际用了多少 fd,别猜
报错时第一件事不是改配置,是确认是不是真到了上限:
-
lsof -p $(pgrep mysqld) | wc -l—— 统计当前打开的 fd 总数 -
cat /proc/$(pgrep mysqld)/limits | grep "Max open files"—— 看内核对该进程实际生效的软硬限制(注意:这个值 ≠ulimit -n,因为 mysqld 是被 systemd 拉起来的,不继承 shell 的 limits)
如果前者(比如 800)远小于后者(比如 1024),说明根本没到系统瓶颈,问题在 SQL 层:可能是 ORDER BY 生成磁盘临时表、JOIN 字段类型不匹配导致索引失效、或存储过程中游标没 CLOSE。
systemd 环境下必须显式配 LimitNOFILE
/etc/security/limits.conf 在 systemd 管理的服务中默认不生效,这是最常卡死的地方:
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
- 找到 service 文件:
systemctl cat mysqld或find /usr/lib/systemd/system /etc/systemd/system -name "*mysql*.service" - 在
[Service]段末尾添加:LimitNOFILE=65536 - 执行:
systemctl daemon-reload && systemctl restart mysqld - 验证:
cat /proc/$(pgrep mysqld)/limits | grep "Max open files"输出应与你设的值一致;若仍是 1024,说明 service 文件改错位置,或被其他同名 unit 覆盖了
open_files_limit 在 my.cnf 里怎么设才不白写
这个参数不是“设多少就用多少”,MySQL 启动时会取三者最大值再受制于系统限制:
10 + max_connections + (table_open_cache * 2)max_connections * 5- 你配置的
open_files_limit值(或默认 5000)
但最终不会超过 /proc/$pid/limits 中的上限。所以建议:
-
my.cnf里设为LimitNOFILE值的 80%~90%,例如 systemd 设了 65536,my.cnf就写open_files_limit = 55000 - 值必须是纯整数,不能带单位(如
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
真正生效的关键永远是:service 文件改了、daemon-reload 了、restart 了,且 cat /proc/$(pgrep mysqld)/limits 确认值已更新——少一步都白干。










