mysql容器必须显式限制内存和cpu,否则innodb_buffer_pool_size会失效并触发oom;-m和--cpus是启动前提,需严格对齐配置,如2g内存对应1.2~1.4g buffer pool,并通过docker inspect和show variables验证生效。

MySQL容器必须显式限制内存,否则innodb_buffer_pool_size会失效,极易触发OOM被kill。
为什么-m和--cpus不是可选项,而是启动前提
容器里没有“物理内存”概念,mysqld进程看到的是宿主机全部内存。若不加-m 2g,它会按默认规则把innodb_buffer_pool_size设为总内存的75%,远超容器实际配额——结果就是Linux内核OOM Killer直接干掉MySQL进程,日志里只留一句Killed process (mysqld)。
CPU同理:--cpus=2不仅限制上限,更关键的是让MySQL的并发线程调度有确定性。不设时,高负载下大量线程争抢CPU,innodb_thread_concurrency等参数失去意义,show processlist里常看到一堆statistics或preparing状态卡住。
- 必须先用
docker run -m 2g --cpus=2跑起来,再调my.cnf - 切勿在没设
-m的情况下直接改innodb_buffer_pool_size,等于自欺欺人 -
--cpus值建议取整数(如2、4),避免小数(如1.5)引发调度抖动
innodb_buffer_pool_size必须严格对齐容器内存限制
这个值不是“越大越好”,而是要和-m值形成硬约束关系。设成1.8g却给容器只配2g,剩下200MB要分给连接线程、排序缓存、临时表等,一并发上来就内存吃紧。
- 容器内存为
2g→innodb_buffer_pool_size=1.2g~1.4g(60%~70%) - 容器内存为
4g→innodb_buffer_pool_size=2.4g~2.8g - 永远留至少512MB给OS和MySQL其他内存消耗,别算满
- 在
my.cnf里写死具体字节数,别用百分比(MySQL 8.0+不支持百分比语法)
避免CPU限制导致性能反降的三个实操细节
单纯加--cpus=2可能让查询变慢,尤其当宿主机CPU核心数多于容器分配数时。
- 用
--cpuset-cpus="0-1"绑定固定核心,比--cpus=2更稳定,减少跨NUMA节点访问延迟 - 确认宿主机未开启
intel_idle.max_cstate=1之类节能策略,否则容器内wait/io时间飙升 - 如果应用大量使用
LOAD DATA INFILE或大事务,适当调高innodb_read_io_threads和innodb_write_io_threads(但不超过--cpus值的一半)
检查是否真的生效:三行命令快速验证
别信配置文件,要看运行时真实值。
- 查容器实际内存限制:
docker inspect mysql-container | grep -i memory - 查MySQL当前buffer pool大小:
mysql -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';" - 查CPU使用是否被掐住:
docker stats mysql-container --no-stream | grep -E "(CPU|MEM)",观察CPU%是否长期卡在接近--cpus设定值
最常被忽略的是:很多人设了-m 4g,但my.cnf里还写着innodb_buffer_pool_size=3g,以为省了1G给系统——其实这1G早被其他MySQL线程和OS悄悄吃光了,最后还是OOM。内存限制和配置必须当成一个原子单元来调。











