mysql 8.028 服务器的内存使用率高于90%
1. 使用 top
, htop
, free -m
, vmstat
, ps
等命令查看整体系统内存使用。
1.1top查mysql
$ top -p $(pgrep mysqld)
- 服务器总内存:32GB
- MySQL 当前内存占用:5.4%(32*0.054
1.7GB)
所以,占内存的进程不是mysql
1.2top查看系统
top ---> 按b, x ---> 按 > , 高亮%MEM
发现,有很多zbxTrapperSumItem.py
经查,这个脚本是系统的计划任务,1分钟执行一次,每次耗时不到5秒。出现几百个僵尸/挂起进程是因为脚本中有一个数据库查询(数据库地址更换了),后面要优化脚本了。
# 系统层面存在很多这样的挂起进程
......
root 3389649 3389648 0 Mar27 ? 00:00:00 /usr/bin/python3 /opt/zbxTrapperTPS/zbxTrapperSumItem.py
......
1.3使用 pkill
一次性终止所有相关进程
pkill -f zbxTrapperSumItem.py
2. 常用排查sql
1. 查看 MySQL 当前实际使用的内存:
SHOW ENGINE INNODB STATUSG;
重点关注 BUFFER POOL AND MEMORY
部分。
2. 使用 SQL 查询查看内存分配情况(需要 performance_schema):
SELECT EVENT_NAME,
CURRENT_COUNT_USED,
CURRENT_NUMBER_OF_BYTES_USED / (1024 * 1024) AS MB_USED
FROM performance_schema.memory_summary_global_by_event_name
WHERE EVENT_NAME LIKE 'memory/%'
ORDER BY MB_USED DESC;
3. 实时查看 buffer pool 使用情况:
SELECT
(SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Innodb_buffer_pool_pages_data') * 16 / 1024 AS used_mb,
(SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Innodb_buffer_pool_pages_free') * 16 / 1024 AS free_mb,
(SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Innodb_buffer_pool_pages_total') * 16 / 1024 AS total_mb;
4. 检查是否有其他内存消耗源
-- 查看各模块内存使用情况(需开启 performance_schema)
SELECT EVENT_NAME,
CURRENT_NUMBER_OF_BYTES_USED / (1024 * 1024) AS MB_USED
FROM performance_schema.memory_summary_global_by_event_name
WHERE EVENT_NAME LIKE 'memory/%'
ORDER BY MB_USED DESC;
5. 优化连接数与会话内存
每个连接也会分配一定内存(如 sort_buffer_size
, join_buffer_size
等),如果连接数多或某些查询效率低,也可能导致内存过高。
SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL VARIABLES LIKE 'max_connections';
SHOW GLOBAL VARIABLES LIKE 'thread_stack';
6. 查看当前 Sleep 连接数
SELECT COUNT(*) AS sleep_connections
FROM information_schema.processlist
WHERE command = 'Sleep';
-
优化 MySQL 配置参数
[mysqld]
wait_timeout = 600 # 非交互式连接的空闲超时时间(单位:秒),建议设为 10 分钟
interactive_timeout = 600 # 交互式连接的空闲超时时间
修改后重启 MySQL 或通过 SQL 动态修改
SET GLOBAL wait_timeout = 600;
SET GLOBAL interactive_timeout = 600;
-
杀掉当前 Sleep 连接(临时处理)
SELECT CONCAT('KILL ', id, ';') AS kill_command
FROM information_schema.processlist
WHERE command = 'Sleep' AND time > 60;