MySQL 8.0 容器启动即占300–500MB内存,主因是innodb_buffer_pool_size按宿主机内存自动设为75%、performance_schema默认开启并预分配大量监控表、连接缓冲区预分配过高;须显式配置buffer_pool(如512MB容器设128M)、禁用performance_schema、下调max_connections等参数,并确保总内存≤容器限制的60%。

MySQL 8.0 容器一启动就占 300–500MB 内存,不是容器本身的问题,而是官方镜像在无显式配置时,按宿主机内存推算 innodb_buffer_pool_size、默认开启 performance_schema,且预分配大量连接缓冲区导致的。虚机里你手动配过,容器里它“自动猜”,结果猜得太高。
innodb_buffer_pool_size 必须显式覆盖
这是内存占用最大变量。Docker 内没有 cgroup 感知能力,MySQL 8.0 官方镜像会读取宿主机总内存(比如 16GB),设 innodb_buffer_pool_size = 12G —— 即使你只给容器 --memory=512m,它也照设不误,OOM 就是分分钟的事。
- 对 512MB 容器:设
innodb_buffer_pool_size = 128M(不超过容器内存的 30%) - 对 1GB 容器:设
innodb_buffer_pool_size = 256M~384M,留出空间给日志缓冲、排序缓冲等其他开销 - 该值必须写入挂载到
/etc/mysql/conf.d/下的配置文件(如lowmem.cnf),SET GLOBAL修改重启即丢 - 别碰
innodb_buffer_pool_chunk_size,除非你明确需要动态调整;默认值即可
performance_schema = 0 是最有效的单步降内存操作
它默认启用 800+ 张监控表,每个连接再分配独立结构体,空载就吃掉 80–120MB。开发、测试、低负载场景完全不需要。
- 配置中写
performance_schema = 0(不是off或OFF,后者部分版本不识别) - 顺手关连带项:
table_definition_cache = 200、table_open_cache = 128,避免缓存膨胀 - 验证是否生效:
SELECT VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'performance_schema';应返回OFF
连接与临时表参数要同步下调
MySQL 启动时为每个连接预分配缓冲区,max_connections 设高了,基线内存直接抬升。临时表失控也会触发磁盘落地,但先爆的是内存。
-
max_connections = 50(非高并发场景足够;每连接多占约 2–3MB) -
tmp_table_size = 16M、max_heap_table_size = 16M(防止 GROUP BY 等操作生成巨型内存临时表) -
innodb_log_buffer_size = 4M(默认 16M,日志写入不频繁时可压) -
key_buffer_size = 8M(MyISAM 已淘汰,仅系统表残留使用,设小即可) - 所有参数必须放在
[mysqld]段下,且确保挂载路径是/etc/mysql/conf.d/(官方镜像会自动加载!includedir)
最容易被忽略的是:这些参数必须全部落盘到配置文件,且挂载进容器——docker run -e 传参或 SET GLOBAL 都无法持久。另外,容器内存限制(--memory)和 MySQL 内部参数之间要有余量,建议 MySQL 总内存占用 ≤ 容器限制的 60%,否则仍可能被 OOM killer 杀掉。


















