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

目录标题

      • **一、问题现象**
      • **二、核心排查步骤**
        • **1. 参数检查**
        • **2. 内存使用分析**
        • **3. 存储过程/函数/视图检查**
        • **4. 操作系统级检查**
      • **三、解决方案**
        • **1. 调整MySQL配置**
        • **2. 关闭透明大页(THP)**
        • **3. 优化查询与存储过程**
        • **4. 硬件与环境优化**
      • **四、总结**

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

一、问题现象

  • 内存占用异常 :通过top命令发现MySQL进程(mysqld)占用了90.7%的物理内存(56.5G/62G)。
  • 系统负载:CPU使用率较低(1.3%),但内存几乎耗尽。

二、核心排查步骤

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

  • 关键内存参数 :

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

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

    sql 复制代码
    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。

  • 分事件内存占用:

    sql 复制代码
    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(复制相关缓存)。
  • 用户级内存统计:

    sql 复制代码
    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. 存储过程/函数/视图检查
  • 存储过程与函数:

    sql 复制代码
    SELECT Routine_schema, Routine_type 
    FROM information_schema.Routines 
    WHERE Routine_schema NOT IN ('mysql','information_schema','performance_schema','sys');

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

  • 视图与触发器:

    sql 复制代码
    SELECT TABLE_SCHEMA, COUNT(TABLE_NAME) FROM information_schema.VIEWS;
    SELECT TRIGGER_SCHEMA, COUNT(*) FROM information_schema.triggers;

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

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

    bash 复制代码
    ps -eo user,pid,vsz,rss | grep mysqld

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

  • 内存映射分析:

    bash 复制代码
    pmap -d <mysql_pid> | tail -1

    关键指标:

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

    bash 复制代码
    cat /sys/kernel/mm/transparent_hugepage/enabled

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

三、解决方案

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

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

    ini 复制代码
    tmp_table_size = 256M
    max_heap_table_size = 256M
2. 关闭透明大页(THP)
  • 临时关闭 :

    bash 复制代码
    echo never > /sys/kernel/mm/transparent_hugepage/enabled
    echo never > /sys/kernel/mm/transparent_hugepage/defrag
  • 永久关闭 :
    在/etc/rc.local中添加:

    bash 复制代码
    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_bytes和pmap持续观察内存变化。

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

相关推荐
野生数据人几秒前
ES DSL 转 SQL 速查表:20 条子句对照 + 一条能直接跑的改写示例
大数据·数据库
野生数据人1 分钟前
采集链路改投 Doris 速查手册:三条路径对照、output 配置项清单、报错处理表
大数据·数据库
救救孩子把14 分钟前
AI面试八股文-07_6-向量数据库索引详解
数据库·人工智能·面试·向量数据库·hnsw
李白客1 小时前
国产数据库"实际用户增长"怎么核验?先定口径,再谈第一
数据库
数据工匠老o1 小时前
一张 5 亿行的表按月分区后,清理历史数据从几小时变成了几秒
数据库·sql
hwscom2 小时前
几分钟开防护,SQL和XSS注入全被护卫神挡住
数据库·sql·xss
石小千2 小时前
Redis开启ACL认证
数据库·redis·缓存
东风微鸣2 小时前
把 Tailscale 接进 Prometheus 监控
java·数据库·prometheus
wno7042 小时前
MYSQL 常用合并函数
android·数据库·mysql
东风微鸣2 小时前
一次断电引发的血案:Ubuntu 26.04 升级中断后的完整救援实录
数据库·ubuntu·postgresql