MySQL默认启动内存100–300MB,但实际占用取决于innodb_buffer_pool_size配置;5.7/8.0默认值常过小,需按场景手动设置,否则引发缓存命中率低、慢查询、OOM等问题。

MySQL 5.7/8.0 默认安装后吃多少内存
MySQL 启动后不加载任何业务数据时,mysqld 进程通常占 100–300MB 内存,但这只是表象。真正影响内存占用的是缓冲区配置,尤其是 innodb_buffer_pool_size —— 它默认在 5.7 是 128MB,8.0 是 128MB(Linux)或自动设为物理内存的 75%(Windows),但很多包管理器(如 Ubuntu 的 apt install mysql-server)会忽略这点,直接用极小值启动。
常见错误现象:SHOW ENGINE INNODB STATUS 显示 Buffer pool hit rate 长期低于 950/1000;慢查询频发但 CPU 不高;top 看 mysqld RSS 持续增长后卡住。
- 开发机(4GB 内存):建议手动设
innodb_buffer_pool_size = 512M,别超 1.5GB - 生产环境(16GB+):起步设为物理内存的 50%~75%,但需预留至少 2GB 给 OS 和其他进程
- 容器部署(Docker):必须用
--memory限制,并在my.cnf中显式设置innodb_buffer_pool_size,否则 MySQL 可能按宿主机内存计算,OOM 被 kill
CPU 核心数对 MySQL 并发性能的实际影响
MySQL 单连接基本是单线程工作(除并行查询、InnoDB 后台线程等少数场景),所以「CPU 核越多越快」只在并发连接数高、且 SQL 能有效分摊到多核时才成立。瓶颈常不在 CPU,而在磁盘 I/O 或锁竞争。
使用场景判断:
- OLTP(如电商订单):16 个活跃连接 + 复杂事务 → 4 核足够;若连接数常超 200,需关注
innodb_thread_concurrency(8.0 已废弃,靠innodb_read_io_threads/innodb_write_io_threads调整 I/O 线程数) - OLAP(大表 JOIN、GROUP BY):开启
innodb_parallel_read_threads(8.0.14+)可利用多核,但仅对全表扫描生效,且受read_buffer_size限制 - 复制延迟高:检查
SHOW SLAVE STATUS中Seconds_Behind_Master,若 CPU 持续 100% 且Slave_SQL_Running_State停在 “executing” —— 很可能是单线程 apply event 成为瓶颈,考虑升级到 8.0+ 的并行复制(slave_parallel_type = LOGICAL_CLOCK)
docker run mysql 容器为啥一启动就 OOM?
根本原因是 MySQL 启动时读取系统内存总量(不是容器限制值),然后按比例分配 innodb_buffer_pool_size。比如宿主机 64GB,容器只给 2GB 内存,但 MySQL 仍可能申请 32GB 缓冲池,立刻被 Linux OOM Killer 干掉。
实操建议:
- 必须挂载自定义
my.cnf,明确写死innodb_buffer_pool_size = 512M - Docker 启动加参数:
--memory=2g --memory-swap=2g --oom-kill-disable=false(后者禁用反而危险,保持默认) - 验证方式:进容器执行
mysql -e "SELECT @@innodb_buffer_pool_size;",结果应接近你设的字节数,而非 GB 级 - 别信“自动适配”,MySQL 官方镜像的
entrypoint.sh仅处理MYSQL_ROOT_PASSWORD类变量,不解析内存限制
为什么调大 buffer_pool 后查询反而变慢?
这不是错觉。当 innodb_buffer_pool_size 设得过大(尤其接近物理内存上限),会导致 OS 缺页频繁,swap 开启后性能断崖下跌;更隐蔽的是:InnoDB 在初始化 buffer pool 时会预分配并清零内存,这个过程阻塞整个实例启动,且首次查询前要完成 page 加载,造成「冷启动延迟」。
容易踩的坑:
- 监控
Innodb_buffer_pool_wait_free状态变量,值持续 > 0 表示 buffer pool 不够用或碎片严重 - 避免在
my.cnf中写innodb_buffer_pool_size = 70% of RAM—— MySQL 不支持百分比语法,会当成 70 字节,启动失败 - 线上调整该值必须重启 MySQL(8.0.22+ 支持动态调整,但仅限增,且需满足
innodb_buffer_pool_chunk_size * N对齐) - buffer pool 大小不是越大越好,它和
innodb_log_file_size强相关:log file 太小 + buffer pool 太大会导致频繁 checkpoint,拖慢写入
最常被忽略的一点:MySQL 的内存占用不是静态的。连接数、临时表、排序缓冲(sort_buffer_size)、join 缓冲(join_buffer_size)都是每个连接独占,开 200 个连接时,哪怕每个只用 2MB,额外内存也超 400MB —— 这部分不会体现在 innodb_buffer_pool_size 里。











