必须同时配置--memory-swap与-m,且docker compose中cpus需加引号;仅设-m和--cpus易致oom或cpu失控,须通过docker stats和cgroup文件验证实际生效。

直接加 --cpus 和 -m 就能生效,但只设这两个参数大概率会出问题——内存超限被杀、CPU调度不稳、swap 暗中拖慢响应,关键在配套参数必须同步配齐。
内存限制必须配 --memory-swap,否则实际可用翻倍
MySQL 8.0 启动后常驻内存 + 缓冲池(innodb_buffer_pool_size)容易接近上限,-m 512m 单独使用时,Docker 默认开启等量 swap(即最多用 512MB 物理内存 + 512MB swap),OOM 行为不可控:内核可能杀 mysqld 进程而非整个容器,导致 MySQL 假死或连接拒绝。
正确做法是显式禁用 swap 或严格约束总量:
-
-m 512m --memory-swap=512m:物理内存 + swap 总和 ≤ 512MB,等效禁用 swap - 避免
--memory-swap=-1(启用无限 swap)或完全不写该参数(默认启用等量 swap) - 若容器需短时爆发内存(如大批量导入),可设
--memory-reservation=256m作软限制,缓解宿主机内存紧张时的强回收
--cpus 是最稳的 CPU 限制方式,慎用 --cpu-shares
MySQL 8.0 的查询执行、日志刷盘、复制线程对 CPU 时间敏感,--cpu-shares 仅在多容器争抢 CPU 时按权重分配,空闲时仍可占满全部核心,无法防止单个慢查询拖垮整机。
推荐用 --cpus 设绝对上限:
-
--cpus="0.75":限制最多使用 75% 的单核算力(适合轻量业务库) -
--cpus="2.0":允许跨核调度,但总时间不超 2 个逻辑核心 - 避免
--cpuset-cpus="0"绑定单核——MySQL 多线程模型天然需要多核协同,硬绑定易引发锁等待堆积
Docker Compose 中配置要注意字符串格式和字段层级
YAML 对缩进和类型敏感,cpus 必须写成字符串(带引号),memswap_limit 不是标准字段,得用 memory_swap 或靠 memory + memory_swap 配对。
正确写法示例:
version: "3.8"
services:
mysql8:
image: mysql:8.0
deploy:
resources:
limits:
cpus: '0.75'
memory: 512M
memory_swap: 512M
reservations:
memory: 256M
-
cpus: 0.75(不带引号)会被 YAML 解析为 float,Docker Compose v2+ 拒绝启动 -
memory_swap字段名不能写成memswap_limit或swap,否则静默忽略 -
reservations下的memory是软保底,不影响 OOM 触发逻辑,仅用于 Swarm 调度
验证是否真生效,别只信启动命令
参数写错、Docker 版本低、内核 cgroup v1/v2 差异都可能导致限制未加载。必须动手查:
- 运行中查实时用量:
docker stats mysql8看 MEM USAGE / LIMIT 是否稳定在设定值附近 - 查实际内核限制:
docker exec mysql8 cat /sys/fs/cgroup/memory/memory.limit_in_bytes,输出应为设定值 × 1024²(如 512MB → 536870912) - 查 CPU 配置:
docker inspect mysql8 | grep -A 3 NanoCpus,值应为设定 cpus × 1e9(如 0.75 → 750000000) - 如果
memory.limit_in_bytes显示9223372036854771712(即 -1),说明内存限制根本没生效
最容易被忽略的是 --memory-swap 的默认行为——它不是“可选项”,而是内存限制的组成部分;还有就是 Compose 里 cpus 必须加引号这个反直觉细节。设了不等于起了,一定得用 docker stats 和 /sys/fs/cgroup/ 下的原始值交叉验证。











