MySQL / PostgreSQL 针对 cgroups(v2)的调优清单
按 “必须做 / 强烈建议 / 高级可选 / 绝对不要” 分级,并且区分 MySQL 与 PostgreSQL 的差异。
适用前提
- RHEL 9 / AlmaLinux 9(cgroups v2)
- systemd 管理服务
- 裸机 / VM / 专用节点(不是混部)
数据库使用 cgroups 的原则是:“只用 accounting,不用弹性限制”
也就是:
- ❌ 不要用来“压”
- ✅ 只用来“隔离、保护系统”
systemd(推荐)
[Service]
CPUQuota=infinity
或直接不设置(默认无限)
📌 CPU throttling = TPS 抖动 = 慢查询爆炸
CPUWeight=100
- 默认 100
- 可适当提高(200~500)
🔥 强烈建议(数据库专用节点)
AllowedCPUs=0-15
或手工:
cpuset.cpus=0-15
📌 防止调度抖动、跨 NUMA
- 不要用 –cpus=2
- 不要用 CPUQuota=200%
- 不要在高峰期动态改 quota
MemoryMax=infinity
📌 memory.max = OOM 定时炸弹
MemorySwapMax=0
或系统级:
swapoff -a
MySQL
innodb_buffer_pool_size = 70%~80% RAM
PostgreSQL
shared_buffers = 25% RAM
effective_cache_size = 70% RAM
MemoryHigh=90%
作用:
- 保护宿主
- 不直接 kill 数据库
📌 memory.high > memory.max
echo 1 > memory.oom.group
或 systemd:
OOMPolicy=kill
📌 防止“半死不活”
- 不要用 docker -m 64g
- 不要在数据库容器里用 swap
- 不要让 kubelet 管数据库内存
- MySQL / PG 数据目录:
- ❌ overlay
- ✅ hostPath / local disk / raw block
IOReadBandwidthMax=
IOWriteBandwidthMax=
📌 数据库 不是 batch IO
IOWeight=100
有混部时:
- DB:200
- 普通服务:50
- 不要 blkio throttle DB
- 不要多 DB 共享一个限速盘
TasksMax=16384
📌 防 fork 炸弹
📌 MySQL / PG 都可能短时间拉高线程
- 不要用默认 512
- 不要无限(会拖死宿主)
AllowedCPUs=0-15
AllowedMemoryNodes=0
或启动命令:
numactl --cpunodebind=0 --membind=0
echo 0 > /proc/sys/kernel/numa_balancing
📌 尤其 MySQL
MySQL
innodb_buffer_pool_size
innodb_use_large_pages=ON
PostgreSQL
huge_pages=on
📌 HugePages + cgroups = 稳定延迟
[Service]
CPUQuota=infinity
CPUWeight=200
MemoryMax=infinity
MemoryHigh=90%
MemorySwapMax=0
OOMPolicy=kill
TasksMax=16384
IOWeight=200
AllowedCPUs=0-15
AllowedMemoryNodes=0
| 项目 | MySQL | PostgreSQL |
|---|---|---|
| NUMA 敏感 | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| OOM 容忍 | 极差 | 较好 |
| HugePage | 强烈推荐 | 推荐 |
| IO 抖动 | 极敏感 | 敏感 |
| cgroup 容忍 | 低 | 中 |
- ❌ memory.max + 高并发
- ❌ CPUQuota + 峰值流量
- ❌ overlay2 + fsync
- ❌ swap + 数据库
- ❌ NUMA 不绑
- ❌ 混部 DB
数据库的 cgroups 不是“限制器”,而是“保护壳”。
如果你在“压数据库”,说明架构已经错了。