mysql文件句柄不足需同步调整systemd的limitnofile和内核fs.file-max,缺一不可;仅改ulimit或limits.conf无效,必须通过systemctl edit mysqld设置limitnofile=65536并重载重启,再验证/proc/pid/limits确认生效。

MySQL 进程的文件打开数限制,不能只靠 ulimit 命令临时设置——它根本不会生效。 因为 MySQL 通常由 systemd 管理(如 mysqld.service),而 systemd 启动的服务完全忽略你终端里执行的 ulimit -n,也不读取 /etc/security/limits.conf,除非你额外配置。
查清楚 MySQL 当前实际用的是哪个 nofile 限制
别猜,直接看进程真实值:
- 先拿到 MySQL 主进程 PID:
pidof mysqld或systemctl show --property MainPID mysqld | cut -d'=' -f2 - 查内核级限制:
cat /proc/<code>PID/limits | grep "Max open files" —— 这才是 MySQL 真正在用的值 - 如果显示
1024或4096,说明没配对;若显示65536但仍有Too many open files报错,得继续查fs.file-max和连接数配置是否匹配
必须改 systemd service 文件里的 LimitNOFILE
这是最可靠、最常用的方式,适用于所有主流发行版(Ubuntu/CentOS/Rocky):
- 编辑服务单元:
sudo systemctl edit --full mysqld(推荐)或sudo nano /etc/systemd/system/mysqld.service - 在
[Service]段下添加(不要加在 [Unit] 或 [Install] 里):LimitNOFILE=65536 - 保存后重载并重启:
sudo systemctl daemon-reload && sudo systemctl restart mysqld - 验证是否写入成功:
systemctl show mysqld | grep LimitNOFILE;再查进程确认:cat /proc/$(pidof mysqld)/limits | grep "Max open files"
别漏掉系统级总容量:fs.file-max
LimitNOFILE=65536 是单个进程上限,但整个系统能分配的文件描述符总数由 fs.file-max 控制。如果它太小(比如默认的 84576),多个高并发服务一起开就可能耗尽:
- 查看当前值:
cat /proc/sys/fs/file-max - 临时调高:
sudo sysctl -w fs.file-max=2097152 - 永久生效:往
/etc/sysctl.conf追加一行:fs.file-max = 2097152,再运行sudo sysctl -p - 注意:这个值不是越大越好,x86_64 下理论最大约 4194304,但设到 2M 已足够支撑千级并发 MySQL 实例
为什么 limits.conf 和 /etc/profile 通常无效
这些地方常被误用,但对 systemd 管理的 MySQL 几乎不起作用:
-
/etc/security/limits.conf只对 PAM 登录会话有效(比如 SSH 登录后手动启 mysqld),systemd 服务启动不走这套流程 - 在
/etc/profile或~/.bashrc里写ulimit -n 65536,只影响交互式 shell,不影响systemctl start mysqld - 用
sudo -u mysql /usr/bin/mysqld手动启动?那才可能继承 limits.conf —— 但这不是生产部署方式,且容易丢失日志、信号处理等 systemd 特性
真正起效的只有两层:systemd 的 LimitNOFILE 控制单进程,fs.file-max 控制全系统总池子。中间任何一层没对齐,MySQL 就会在高连接数下突然报错“Too many open files”,而且错误日志里往往不提示是哪一层崩了。











