systemd下必须先配置LimitNOFILE,否则my.cnf中open_files_limit形同虚设;需通过systemctl edit mysqld添加[Service] LimitNOFILE=65535,再daemon-reload并restart,最后用/proc/PID/limits和SHOW VARIABLES双重验证。

systemd 下 LimitNOFILE 必须先设,否则 my.cnf 里的 open_files_limit 形同虚设
MySQL 8.0 默认由 systemd 管理,它压根不读 /etc/security/limits.conf,也不继承终端的 ulimit -n。你往 my.cnf 的 [mysqld] 段里写 open_files_limit = 65535,启动后查 SHOW VARIABLES LIKE 'open_files_limit'; 很可能还是 1024 或 5000——这不是配置没生效,是 MySQL 根本没拿到那么多句柄。
必须显式告诉 systemd:这个服务允许开多少文件。操作步骤如下:
- 运行
sudo systemctl edit mysqld(服务名可能是mysql或mariadb,用systemctl list-units | grep mysql确认) - 在打开的编辑器中写入:
[Service] LimitNOFILE=65535
- 保存退出,执行
sudo systemctl daemon-reload && sudo systemctl restart mysqld - 验证是否加载成功:
systemctl show mysqld | grep LimitNOFILE,应输出LimitNOFILE=65535
my.cnf 中 open_files_limit 的写法和取值逻辑
open_files_limit 不是硬上限,而是 MySQL 启动时向系统申请的目标值。它最终生效值 = min(你配的值, systemd 的 LimitNOFILE, 内核 fs.file-max)。所以它必须是纯数字,不能带单位,也不能放错位置。
使用ydata-profiling(前身为pandas-profiling)生成全面的数据质量报告,包含相关性分析、缺失值模式和基数检测。导出交互式HTML仪表板和JSON摘要。
- 只允许出现在
[mysqld]段下,[client]或[mysqld_safe]里写无效 - 值建议设为
LimitNOFILE的 80%~90%,例如 systemd 设了 65535,my.cnf里写open_files_limit = 55000,留余量给 error log、slow log、socket、临时表等内部使用 - 不要设为 0 或空值,MySQL 会退化为保守估算(常是 5000 左右)
- 避免设得比
max_connections * 5或max_connections + table_open_cache * 2小,否则连接数一高就卡住
验证是否真生效:别只信 SHOW VARIABLES
SHOW VARIABLES 显示的是 MySQL 自己“认为”的值,不是进程实际拿到的限制。真正生效的,是内核对 mysqld 进程施加的上限。
- 查进程真实限制:
cat /proc/$(pgrep mysqld)/limits | grep "Max open files",输出类似Max open files 65535 65535 files才算到位 - 再进 MySQL 查:
SHOW VARIABLES LIKE 'open_files_limit';,该值应略小于或等于上一步的 soft limit(MySQL 会扣掉几十个用于内部用途) - 如果两者差距过大(比如进程限制是 65535,但 SQL 返回 1024),说明
my.cnf配置未被读取,或服务名不匹配导致 unit 文件没生效 - 别跳过重启:
systemctl reload mysqld不触发重新申请 fd,必须restart
innodb_open_files 不是用来解决 Too many open files 的
看到报错 “Too many open files”,有人会顺手调大 innodb_open_files,这是典型误操作。这个参数只控制 InnoDB 同时打开多少个 .ibd 表空间文件,跟连接数、临时表、日志文件等完全无关。
- 默认值通常够用(300 或更高),除非你有上万张独立
innodb_file_per_table表且频繁访问 - 乱调高反而浪费内存,还可能挤占其他关键 fd 资源
- 真正要盯紧的是
table_open_cache和max_connections的组合是否合理,它们直接影响 fd 消耗速率 - 如果
lsof -p $(pgrep mysqld) | wc -l远低于/proc/PID/limits上限,问题大概率出在 SQL 层:未释放游标、ORDER BY/GROUP BY 生成磁盘临时表、JOIN 字段类型不匹配导致索引失效等
最易被忽略的一点:改完所有配置后,必须双重验证——既要看 /proc/PID/limits 的真实上限,也要看 lsof -p $(pgrep mysqld) | wc -l 的实时占用。前者告诉你“天花板在哪”,后者告诉你“现在离天花板还有多远”。光有上限不等于安全,占用持续逼近上限才是真风险。

















