MySQL内存使用率高问题排查与解决方案:

一、问题现象

  • 内存占用异常:通过top命令发现MySQL进程(mysqld)占用了90.7%的物理内存(56.5G/62G)。

  • 系统负载:CPU使用率较低(1.3%),但内存几乎耗尽。

二、核心排查步骤

1. 参数检查
  • MySQL版本:8.0.39(未开启慢查询日志)。

  • 关键内存参数

SHOW VARIABLES LIKE 'innodb_buffer_pool_size';  -- 12G(配置较低,建议调整为总内存的70%~80%)
SHOW VARIABLES LIKE 'tmp_table_size';           -- 16M(临时表内存限制过小)
  • 临时文件路径/tmp(建议改为专用目录以避免性能问题)。

2. 内存使用分析
  • 全局内存统计

SELECT SUM(CAST(replace(current_alloc,'MiB','') AS DECIMAL(10,2))) 
FROM sys.memory_global_by_current_bytes 
WHERE current_alloc LIKE '%MiB%';

结果:总内存使用约1933.69MB。

  • 分事件内存占用

SELECT event_name, sys.format_bytes(CURRENT_NUMBER_OF_BYTES_USED)
FROM performance_schema.memory_summary_global_by_event_name
ORDER BY CURRENT_NUMBER_OF_BYTES_USED DESC LIMIT 10;

关键发现

  • memory/innodb/buf_buf_pool占用13.29GB(InnoDB缓冲池)。

  • memory/group_rpl/Gcs_xcom::xcom_cache占用1024MB(复制相关缓存)。

  • 用户级内存统计

SELECT user, event_name, current_number_of_bytes_used/1024/1024 AS MB_USED
FROM performance_schema.memory_summary_by_account_by_event_name
WHERE host <> "localhost"
ORDER BY MB_USED DESC LIMIT 10;

发现:特定用户(如zqzh)在memory/temptable/physical_ram中占用65MB。

3. 存储过程/函数/视图检查
  • 存储过程与函数

SELECT Routine_schema, Routine_type 
FROM information_schema.Routines 
WHERE Routine_schema NOT IN ('mysql','information_schema','performance_schema','sys');

结果:多个业务库存在大量存储过程和函数(如bpcbsc等)。

  • 视图与触发器

SELECT TABLE_SCHEMA, COUNT(TABLE_NAME) FROM information_schema.VIEWS;
SELECT TRIGGER_SCHEMA, COUNT(*) FROM information_schema.triggers;

结果:视图和触发器数量较少,非主要内存消耗源。

4. 操作系统级检查
  • 进程内存占用

ps -eo user,pid,vsz,rss | grep mysqld

结果mysqld进程虚拟内存(VIRT)96.2G,物理内存(RES)56.5G。

  • 内存映射分析

pmap -d <mysql_pid> | tail -1

关键指标

  • writeable/private:进程实际占用的私有内存(持续增长可能提示内存泄漏)。

  • 透明大页(THP)检查

cat /sys/kernel/mm/transparent_hugepage/enabled

结果:THP处于开启状态(可能导致内存分配效率低下)。

三、解决方案

1. 调整MySQL配置
  • 增加InnoDB缓冲池

innodb_buffer_pool_size = 48G  -- 根据总内存(62G)调整为77%
  • 优化临时表内存

tmp_table_size = 256M
max_heap_table_size = 256M
2. 关闭透明大页(THP)
  • 临时关闭

echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
  • 永久关闭
    /etc/rc.local中添加:

if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
    echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
    echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi
3. 优化查询与存储过程
  • 分析慢查询:开启慢查询日志,定位低效SQL。

  • 减少存储过程依赖:将复杂逻辑移至应用层,避免存储过程内存泄漏。

4. 硬件与环境优化
  • 增加物理内存:若业务需求增长,考虑升级服务器内存。

  • 迁移临时文件目录:将tmpdir设置为专用高速存储路径。

四、总结

  • 核心问题:MySQL内存使用率高主要由InnoDB缓冲池配置不足、THP机制效率低下及存储过程/函数内存占用引起。

  • 解决重点:调整缓冲池大小、关闭THP、优化查询逻辑。

  • 后续监控:通过sys.memory_global_by_current_bytespmap持续观察内存变化。

通过以上步骤,可显著降低MySQL内存占用并提升稳定性。