目录标题
- **一、问题现象**
- **二、核心排查步骤**
- **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(未开启慢查询日志)。
- 关键内存参数:
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');
结果:多个业务库存在大量存储过程和函数(如
bpc
、bsc
等)。 -
视图与触发器:
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_bytes
和pmap
持续观察内存变化。
通过以上步骤,可显著降低MySQL内存占用并提升稳定性。