MySQL吃掉大量内存,绝大多数场景不是故障,而是它把内存当缓存池用,加上连接数和临时表配置失控,先定位缓冲池、连接缓冲、临时表和慢SQL四处,再按需下调参数即可。
MySQL占用内存过高怎么解决?先把内存流向拆成四块
MySQL把自己当成一个爱囤货的仓库管理员,只要配置允许,它会先把一大块物理内存划成InnoDB缓冲池,用来缓存数据页和索引页,后面每来一个连接,又会单独申请排序缓冲、连接缓冲、读取缓冲,查询一复杂,临时表还会继续从内存里切蛋糕,所以看到内存占用飙升,别急着杀进程,先看四块大头。
InnoDB缓冲池是占内存的第一大户
innodb_buffer_pool_size 控制InnoDB能用多少内存缓存热点数据,这个参数在安装后如果被调大,比如设置成物理内存的一半到七成左右,MySQL启动后就会直接占据对应内存,缓存池越大,磁盘IO越少,查询越快,但低配服务器会立刻吃紧。
- 查看当前设置:
SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; - 查看实际使用情况:
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_%'; - 判断是否该调小:
Innodb_buffer_pool_pages_free长期很大,说明缓存池过大,可以缩小。
每个连接都在偷偷攒小块内存
sort_buffer_size、join_buffer_size、read_buffer_size、read_rnd_buffer_size 这些参数本身单次占用不大,但MySQL会按每个连接分配。max_connections 设置到几百甚至上千,而实际活跃连接只有几十,剩余空闲连接也会预留资源,据统计,相当一部分低配服务器内存告警都与连接数虚高有关,尤其慢查询长时间不释放,内存就会堆高。
- 查看单连接缓冲参数:
SHOW VARIABLES LIKE '%buffer_size'; - 查看当前连接数:
SHOW GLOBAL STATUS LIKE 'Threads_connected'; - 查看最大连接数:
SHOW VARIABLES LIKE 'max_connections';
临时表和内存表会突然切出一块内存

MySQL在做 GROUP BY、ORDER BY、DISTINCT、子查询时,结果集小于 tmp_table_size 和 max_heap_table_size 会直接放内存,一旦多个会话同时创建大临时表,内存占用会瞬间增加,超过阈值后才转磁盘,所以阈值调得过高反而更吃内存。
性能监控本身也在消耗内存
performance_schema 默认开启后会记录大量运行时状态,sys 库查询也依赖它,在低内存服务器上,这一块虽不如缓冲池大,但也可能占到几百兆,如果不需要监控报表,可以关闭。
简米云服务器MySQL内存占用高,常见排查路径
云服务器内存通常比物理机更紧张,2核4G、4核8G这类规格很容易被MySQL挤满,遇到简米云服务器MySQL内存占用高,建议按下面的路径逐层排查,不要一上来就重启。
第一步:用系统命令先确认是谁在吃内存
在服务器终端执行:
free -h看整体内存和SWAP使用top -o %MEM或ps aux --sort=-%mem | head -20找占用最高的进程
mysqld 的RES接近物理内存上限,再进入MySQL内部排查。
第二步:查MySQL全局内存账
登录MySQL后执行:
SELECT FROM sys.memory_global_by_current_bytes LIMIT 10;
这条语句会列出MySQL内部各大内存组件当前占用,缓冲池、连接缓冲、临时表等一目了然,没有 sys 库时也可直接查 performance_schema.memory_summary_global_by_event_name。
第三步:检查是否存在连接泄漏或慢查询堆积
SHOW GLOBAL STATUS LIKE 'Threads_connected';SHOW PROCESSLIST;
如果看到几十上百个 Sleep 连接长期不释放,通常是应用连接池配置出错,再看 Time 列较大的查询,很可能是大事务或未提交事务占用内存。
第四步:确认是否发生SWAP或OOM
SWAP一旦启用,MySQL性能会明显下降,但内存占用数字会看着更稳定,执行:

swapon -sdmesg | grep -i oom
如果日志里出现 Out of memory: Kill process mysqld,说明内存确实不够,需要降低参数或升级配置。
MySQL和PostgreSQL内存占用对比:低配服务器该选谁?
很多人在服务器选型时会问:MySQL和PostgreSQL内存占用对比到底哪个更省资源,业内专家指出,两者内存策略差异明显,不能简单说谁更省。
| 对比项 | MySQL | PostgreSQL |
|---|---|---|
| 核心缓存 | InnoDB缓冲池默认由 innodb_buffer_pool_size 控制,生产环境常设为物理内存一半到七成左右 |
shared_buffers 生产环境通常建议设置为物理内存四分之一左右,其余依赖操作系统page cache |
| 连接内存 | 每个连接分配多个缓冲,连接数高时放大明显 | 每个连接也分配工作内存,但参数控制更细 |
| 临时操作 | 内存临时表阈值由 tmp_table_size 控制 |
work_mem 控制排序和哈希表,单个操作可多次分配 |
| 低配服务器表现 | 参数过多,容易配置失衡导致内存膨胀 | 默认配置相对保守,但复杂查询可能频繁写临时文件 |
行业共识认为,低配服务器选MySQL时,必须手动压住缓冲池和连接数,选PostgreSQL则要把 shared_buffers 调低,并关注 work_mem 与连接数的乘积,二者没有绝对优劣,只看运维习惯。
服务器内存不足时,MySQL参数调整实操清单
先停掉没用的连接和慢查询,再动参数,以下是可验证的调整顺序。
- 降低
innodb_buffer_pool_size:生产环境不要低于物理内存的三分之一,过低会导致频繁刷盘。 - 降低
max_connections:从应用实际并发数出发,留出适量余量即可,不要设成800、1000。 - 调小
sort_buffer_size、join_buffer_size、:这些参数不要全局调大,可在会话级针对慢SQL临时调。
read_buffer_size
- 控制
tmp_table_size和max_heap_table_size:先观察Created_tmp_disk_tables状态,如果磁盘临时表不多,可以适当调小。 - 关闭
performance_schema:在/etc/my.cnf中加入performance_schema=OFF,重启生效。 - 考虑使用jemalloc内存分配器:部分Linux发行版默认glibc malloc在高并发下内存碎片较多,切换jemalloc后可降低RSS。
调整后观察一段时间,不要一次调到底,内存降低的同时,磁盘IO和CPU可能会上升,需要平衡。
MySQL占用大量内存通常由缓冲池、连接级缓冲、临时表和监控组件共同造成,抓住这四块,用 sys 库和 SHOW STATUS 定位清楚,再按业务并发量调整参数,多数低内存服务器都能稳定运行。
MySQL占用内存过高怎么解决?常见问题答疑
mysql占用内存过高怎么解决?
先定位内存大头,执行 SELECT FROM sys.memory_global_by_current_bytes LIMIT 10; 查看缓冲池、连接缓冲和临时表占用,再根据结果降低 innodb_buffer_pool_size、max_connections 以及各类 _buffer_size 参数,如果存在大量Sleep连接或慢查询,先处理连接泄漏和SQL,通常内存会明显回落。
服务器内存不足时MySQL先调哪个参数?
优先调低 innodb_buffer_pool_size 和 max_connections,前者是最大头,后者放大连接级内存,关闭 performance_schema 也能释放一部分内存,调整后重启MySQL并观察SWAP使用情况。
简米云服务器MySQL内存占用高是平台问题吗?
多数情况下不是云平台本身的问题,云服务器内存规格固定,MySQL默认或自定义参数常超出实际需求,先在 free -h 和 dmesg 中确认OOM,再进入MySQL查缓冲池和连接数,按业务规模调整即可,简米云控制台提供的监控曲线也能直接看到内存使用趋势,便于定位是否为慢SQL堆积导致。
图片来源于AI模型,如侵权请联系管理员。作者:酷小编,如若转载,请注明出处:https://www.kufanyun.com/ask/840796.html


评论列表(1条)
这篇文章的内容非常有价值,我从中学习到了很多新的知识和观点。作者的写作风格简洁明了,却又不失深度,让人读起来很舒服。特别是控制部分,给了我很多新的思路。感谢分享这么好的内容!