systemd是mysql资源限制的实际控制面,memorymax=4g、limitnofile=65535、limitfsize=10g必须在[service]段配置才生效,cgroup v2 memory.max和systemd limit*系列是唯一可靠硬限,mysql配置项仅为软提示。

systemd 是现代 Linux 上管理 MySQL 进程资源的实际控制面,MySQL 自身不提供硬性内存/文件数/磁盘写入上限,所有可靠限制必须落在 systemd 层。
MemoryMax=4G 是唯一有效的内存硬限
MySQL 没有 max_memory_mb 这类配置项,innodb_buffer_pool_size 等只是软提示。实际 RSS 内存可能远超配置值,尤其叠加 page cache 和 per-connection 缓冲后。
-
MemoryMax=4G必须写在[Service]段,且单位支持K/M/G/T -
MemoryLimit是 cgroup v1 兼容项,在 cgroup v2(当前默认)下完全无效 - 务必配
MemorySwapMax=0,否则内存压力下 swap 会拖垮响应延迟 - 验证方式:
cat /proc/$(pgrep mysqld)/limits | grep memory,看到Max memory行才生效
LimitNOFILE=65535 才能让 open_files_limit 生效
你在 my.cnf 里写 open_files_limit = 65535 没用——mysqld 进程启动时受 systemd 的 LimitNOFILE 约束,系统级 ulimit 会被忽略。
- 必须在
/etc/systemd/system/mysqld.service.d/override.conf中显式声明LimitNOFILE=65535 - 不要设为
0,那会让 MySQL 自行估算,通常只给到 5000 左右 - 重启后查
SHOW VARIABLES LIKE 'open_files_limit';,结果应接近你设的值(允许少量内核保留) -
/etc/security/limits.conf对 systemd 管理的服务进程完全不起作用
LimitFSIZE=10G 防止磁盘被写爆
innodb_data_file_path 的 max_size 几乎没用,MySQL 不支持数据库级磁盘配额。真正能拦住恶意 INSERT 或 LOAD DATA 的,是 LimitFSIZE。
- 加在 service 文件的
[Service]段:LimitFSIZE=10G - 它限制的是进程可 write()/truncate() 的总字节数,对已打开的大文件无效,但新写入会直接失败
- 错误现象是
OS error code 28: No space left on device,而非 MySQL 报错 - 搭配
innodb_file_per_table=ON(默认开启),后续才能按表做磁盘配额或硬链接隔离
MAX_USER_CONNECTIONS 是账号侧唯一有效手段
MySQL 没有 max_memory_per_user,所有“用户内存限制”都是误导。真正可控的只有连接数,这是防止单个账号拖垮整实例的第一道闸门。
- 用
ALTER USER 'xxx'@'%' WITH MAX_USER_CONNECTIONS 5;,不是GRANT ... WITH - 同一用户名不同 host(如
'app'@'192.168.1.%'和'app'@'localhost')需分别设置 - 查实时连接:
SELECT user, COUNT(*) FROM performance_schema.threads WHERE TYPE = 'FOREGROUND' GROUP BY user; - 设为
0表示不限,生产环境严禁
cgroup v2 的 memory.max 和 systemd 的 Limit* 系列才是真实生效的控制点,MySQL 配置文件里的数值只是建议值,不是契约。漏掉任何一层,都可能在高并发或异常写入时突然触发 OOM 或磁盘满。











