生产级 MySQL 内存占用过高排查指南


一、第一步:区分「缓存虚高」和「真实内存告警」

核心命令

bash

运行

复制代码
free -g
dmesg | grep -i oom

直接判断标准

  1. 只看 2 个核心指标 :

    • 真实可用内存:新版看available、老版(CentOS6)看-/+ buffers/cache行的free
      • ✅ 安全:> 总内存 20%
      • ❌ 真告警:< 总内存 10%
    • Swap 使用量:used > 0且持续上涨 = 物理内存耗尽,性能已受损
  2. 验证是否为缓存虚高(低峰执行,无影响) :

    bash

    运行

    复制代码
    sync; echo 3 > /proc/sys/vm/drop_caches

    执行后内存大幅下降 = 仅为 Linux 文件缓存,属于正常机制,无需处理;内存无变化 = 进程真实占用,继续排查。

  3. 存在 OOM 日志 = 内存已溢出,随时会杀进程宕机。


二、第二步:定位进程,确认是不是 MySQL 的问题

核心命令

bash

运行

复制代码
# 按内存排序看Top10进程
ps aux --sort=-%mem | head -10
# 交互式查看(进入后按大写M按内存排序)
top

关键判断

  • 内存占比最高的进程为mysqld = MySQL 服务占用(注意:/usr/bin/mysql是客户端工具,不是服务进程)
  • 存在陌生高内存进程 = 排查挖矿、僵尸进程或其他业务泄漏。

三、第三步:MySQL 根因定位

1. 查看 MySQL 真实物理内存占用

bash

运行

复制代码
cat /proc/`pidof mysqld`/status | grep VmRSS

输出单位为 KB,除以1024*1024即为 GB 占用。

2. 核心参数排查(最常见根因)

MySQL 90% 内存占用来自innodb_buffer_pool_size(数据 / 索引缓存):

bash

运行

复制代码
# 查看当前配置
mysql -e "show variables like 'innodb_buffer_pool_size';"
# 查看实际已使用缓存
mysql -e "SELECT ROUND(data_size/1024/1024/1024,2) AS used_gb FROM information_schema.innodb_buffer_pool_stats\G"
配置红线
  • 专用数据库服务器:该值不能超过总内存的 70%
  • 混布服务器:不能超过总内存的 40%
  • 反例:64G 内存配置 50G 缓存,叠加连接 / 临时表内存直接占满系统。

3. 慢 SQL / 连接暴涨排查

bash

运行

复制代码
# 查看当前所有活跃查询
mysql -e "show full processlist;"

重点杀:执行时间过长、状态为Sorting result/Copying to tmp table的大查询,这类 SQL 会瞬间吃满内存。

4. 找到生效的配置文件 my.cnf

bash

运行

复制代码
mysql --help | grep "Default options" -A 1

常见路径:/etc/my.cnf > /etc/mysql/my.cnf。


四、直接落地的解决方案

1. 缓冲池配置过大(无需重启,在线修复)

MySQL 5.7.5+/8.0 支持热调整,无业务中断:

sql

复制代码
# 示例:64G内存调整为30G(单位:字节)
mysql -e "set global innodb_buffer_pool_size = 30 * 1024 * 1024 * 1024;"

永久生效:修改 my.cnf 后低峰重启即可。

2. 内存扩容说明

  • ✅ 服务器扩容物理内存不需要重启 MySQL,系统自动识别
  • 扩容后可直接在线调大innodb_buffer_pool_size,无需重启服务

3. 系统级必做优化

bash

运行

复制代码
# 关闭透明大页(MySQL官方要求,避免内存抖动)
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

# 降低Swap使用优先级
echo 10 > /proc/sys/vm/swappiness

一键排查速查表(直接复制执行)

bash

运行

复制代码
# 1. 系统内存定级
free -g && dmesg | grep -i oom
# 2. 高内存进程定位
ps aux --sort=-%mem | head -10
# 3. MySQL真实内存
cat /proc/`pidof mysqld`/status | grep VmRSS
# 4. 缓冲池配置
mysql -e "show variables like 'innodb_buffer_pool_size';"
# 5. 慢SQL排查
mysql -e "show full processlist;"
相关推荐
IT199520 小时前
Fail2Ban 防护 MySQL 实战|登录失败 3 次,IP 封禁 24 小时
数据库·mysql
夕除20 小时前
redis--IO 多路复用(select + poll)
数据库·sql
paopaokaka_luck1 天前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法
lzhdim1 天前
100条常用SQL语句
数据库·sql·mysql·mybatis
天河归来1 天前
从原始消息到业务数据:三层数据架构的设计与实践
数据库·数据仓库·架构
数据库小学妹1 天前
金融数据库成本怎么算?五笔钱加一张TCO表
数据库·金融行业·数据库选型·国产化替代·tco·金融数据库
KaiwuDB1 天前
KaiwuDB 分布式集群扩缩容,从原理到完整操作踩坑总结
运维·数据库·分布式
auspicious航1 天前
PostgreSQL的备份与恢复
数据库·postgresql
这个DBA有点耶1 天前
从 MySQL 到时序数据库:我帮朋友做迁移的完整记录
数据库·架构·dba
泡海椒1 天前
深度解析JQuick-SQL AST到逻辑计划转换机制|分布式SQL原理
数据库·分布式·sql