MySQL进程文件句柄上限由systemd的LimitNOFILE控制,而非ulimit命令或limits.conf;必须通过systemctl edit mysqld设置LimitNOFILE=65536,再daemon-reload并restart,同时同步配置fs.file-max和my.cnf中open_files_limit。

MySQL进程的文件句柄上限由systemd控制,不是ulimit命令能改的
直接在终端里执行ulimit -n 65536对MySQL服务完全无效——它只影响当前shell启动的进程,而mysqld是systemd拉起来的,继承的是systemd自己的限制(通常是1024)。你改了终端的ulimit,systemd根本看不见。
验证方法很简单:cat /proc/$(pidof mysqld)/limits | grep "Max open files"。如果输出显示Soft Limit是1024或4096,说明还没生效,别急着调MySQL配置。
- 别碰
/etc/security/limits.conf:它只对PAM登录会话有效,systemd服务默认不走这套流程 - 别在
/etc/profile或~/.bashrc里写ulimit:只影响交互式shell,不影响systemctl start mysqld - 别用
LimitNOFILE=infinity:某些内核版本会fallback到4096,反而更糟
必须修改systemd service的LimitNOFILE并重载
这是唯一可靠的方式。操作分三步:编辑覆盖配置、重载、重启。注意服务名可能是mysqld或mysql,先确认:systemctl list-units | grep mysql。
- 运行
sudo systemctl edit mysqld(若服务名是mysql则用mysql) - 在打开的编辑器中输入:
[Service] LimitNOFILE=65536
- 保存后执行:
sudo systemctl daemon-reload && sudo systemctl restart mysqld
验证是否写入成功:systemctl show mysqld | grep LimitNOFILE应输出LimitNOFILE=65536;再查进程:cat /proc/$(pidof mysqld)/limits | grep "Max open files",Soft和Hard都得是65536。
别漏掉系统级总容量fs.file-max
LimitNOFILE=65536只是单个进程上限,整个系统能分配的文件描述符总数由fs.file-max控制。如果它太小(比如默认84576),多个高并发服务一起跑就可能耗尽。
- 临时调高:
sudo sysctl -w fs.file-max=2097152 - 永久生效:往
/etc/sysctl.conf追加fs.file-max = 2097152,再运行sudo sysctl -p - 这个值不是越大越好,x86_64下理论最大约4194304,设到2M已足够支撑千级并发MySQL实例
MySQL内部open_files_limit也要同步配
MySQL启动时会向上申请文件句柄数,但它不会自动等于systemd的LimitNOFILE。如果my.cnf里没设open_files_limit,MySQL可能只拿到一个保守值(比如几千),哪怕系统允许65536也没用。
在[mysqld]段下显式设置:
open_files_limit = 65536,然后重启。注意:这个值不能超过systemd的
LimitNOFILE,否则MySQL启动时会报warning并自动下调。
另外,innodb_open_files建议设为open_files_limit的70%左右(比如40000),给binlog、socket、临时文件留余量。别盲目调大innodb_open_files就想解决问题——它只是“想开”,真正“能开”取决于systemd和内核两级限制。
最常被忽略的点是:改完systemd配置后没daemon-reload,或者restart前忘了stop导致旧进程残留;还有人把LimitNOFILE写错位置(比如塞进[Unit]段),结果压根不加载。验证一定要落到/proc/PID/limits,别只信systemctl show输出。


















