MySQL-内存占用分析指令

MySQL Version

mysql> select version();
+------------+
| version()  |
+------------+
| 5.7.39-log |
+------------+
1 row in set (0.00 sec)

Shell Command

# os负载
uptime; 
free -h;
# mysqld进程占用内存
top -b -n 1 | grep mysqld | grep -v mysqld_safe
# os + mysqld
top -b -n 1 -p $(pgrep -n mysqld)

SQL

  • innodb_buffer_pool_size
-- 查看innodb_buffer_pool_size参数(单位GB)
SELECT  @@innodb_buffer_pool_size/1024/1024/1024;
-- 设置参数
SET GLOBAL innodb_buffer_pool_size=2*1024*1024*1024;
-- 查看InnoDB缓存池已分配buffer_size
select * from sys.innodb_buffer_stats_by_schema limit 10;
  • innodb engine status
show engine innodb status\G;
  • processlist
-- 查看当前连接数
select count(*) from information_schema.processlist;
show processlist;
  • max_connections
-- 查看和设置max_connections
show variables like 'max_connections';
SET GLOBAL max_connections = 3500;

-- 查看和设置max_user_connections
SELECT @@max_user_connections;
set global max_user_connections=1000;
SELECT @@max_user_connections;
# 排序统计Server的连接数
mysql -uroot -h$MYSQL_SERVER_IP -p$MYSQL_ROOT_PASSWORD -e "show processlist;" | awk '{print $2" "$4}' | uniq -c | sort -rn | grep -v User | head -n 10
  • slow query
--设置慢查询时间阈值(单位:秒)
set global long_query_time=1;
--关闭 记录没有使用索引的sql
set global log_queries_not_using_indexes=OFF;
--开启记录慢查询日志
set global slow_query_log = 1;
--获取慢查询日志路径
show variables like '%slow_query%';

--关闭记录慢查询日志
set global slow_query_log = 0;
# 过滤 Query_time && Rows_examined
cat slow_query.log | grep Query_time

cat slow_query.log | grep -E 'Query_time: [1-9]'
  • 分析table
-- 查看单表信息
show table status like 'table_name'\G;
show table status from DbName where name='table_name'\G;
-- 查看各个表数据量
SELECT table_name,table_rows FROM information_schema.tables WHERE TABLE_SCHEMA = 'database_name' ORDER BY table_rows DESC limit 10;
-- 查看平均每条记录大小和表的总数据量
SELECT table_name,table_rows,CONCAT(ROUND(SUM((DATA_LENGTH + INDEX_LENGTH) / table_rows) / 1024, 2), ' KB') AS average_row_size,CONCAT(ROUND(SUM(DATA_LENGTH) / (1024 * 1024), 2), ' MB') AS total_data_size, CONCAT(ROUND(SUM(index_length) / (1024 * 1024), 2), ' MB') AS total_index_size  FROM information_schema.tables WHERE TABLE_SCHEMA = 'database_name' AND TABLE_NAME = 'table_name';
  • 开启内存统计
-- 开启内存统计
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'memory/%';
-- 查看是否开启,yes是开启,no是关闭.
select * from performance_schema.setup_instruments where name like 'memory%innodb%' limit 10;

use performance_schema;
show tables like '%memory%';
# my.cnf
[mysqld]
performance-schema-instrument   = 'memory/%=ON'
  • memory_global
select * from sys.memory_global_total;

SELECT SUBSTRING_INDEX(event_name,'/',2) AS code_area, sys.format_bytes(SUM(current_alloc)) AS current_alloc   FROM     sys.x$memory_global_by_current_bytes GROUP BY SUBSTRING_INDEX(event_name,'/',2)   ORDER BY SUM(current_alloc) DESC;

select *  from sys.x$memory_global_by_current_bytes  where event_name like "memory/sql/%"  order by current_alloc desc limit 10;

Case

  • 现象

mysqld进程CPU占用高,内存平均每小时上涨2G,内存持续上涨到80G+,直到耗尽操作系统内存。

  • 排查

上调参数innodb_buffer_pool_size 问题未缓解,开启慢查询,发现大量单表百万行数据的全表扫描慢查询;

清理慢查需SQL表数据,解决慢查询SQL后,mysqld进程运维内存占用平稳。

  • 优化

下调客户端查询参数,限制慢查询的建立的连接数和单个查询连接的缓存数据量。

参考文档

mysql内存查阅 mysql内存分析 - 郭大侠1 - 博客园

MySQL 内存泄露怎样检查 - 墨天轮

MySQL查看线程内存占用情况

分析mysql实例内存使用情况_51CTO博客_mysql内存使用率过高

--统计事件消耗内存,那个event_name排最前,就代表这个事件模块占内存最多.例如:JOIN_CACHE就是join的操作,mem0mem就是客户端连接,没开启统计的话,数据可能并不会很多.
select event_name, concat(CURRENT_NUMBER_OF_BYTES_USED/1024/1024/1024,' GB') AS CURRENT_NUMBER_OF_GB_USED,SUM_NUMBER_OF_BYTES_ALLOC from performance_schema.memory_summary_global_by_event_name order by CURRENT_NUMBER_OF_BYTES_USED desc limit 10;
--统计线程消耗内存,thread_id就是show processlist的thread_id,如果SUM_NUMBER_OF_BYTES_ALLOC为零就代表没开启统计
select thread_id, event_name, concat(CURRENT_NUMBER_OF_BYTES_USED/1024/1024/1024,' GB') AS CURRENT_NUMBER_OF_GB_USED, concat(SUM_NUMBER_OF_BYTES_ALLOC/1024/1024/1024,' GB') AS SUM_NUMBER_OF_GB_ALLOC from performance_schema.memory_summary_by_thread_by_event_name order by CURRENT_NUMBER_OF_BYTES_USED desc limit 10;

--统计账户消耗内存,如果SUM_NUMBER_OF_BYTES_ALLOC为零就代表没开启统计
select USER, HOST, EVENT_NAME, concat(CURRENT_NUMBER_OF_BYTES_USED/1024/1024/1024,' GB')  AS  CURRENT_NUMBER_OF_GB_USED,SUM_NUMBER_OF_BYTES_ALLOC from performance_schema.memory_summary_by_account_by_event_name order by CURRENT_NUMBER_OF_BYTES_USED desc limit 10 ;

--统计主机消耗内存,如果SUM_NUMBER_OF_BYTES_ALLOC为零就代表没开启统计
select HOST, EVENT_NAME, concat(CURRENT_NUMBER_OF_BYTES_USED/1024/1024/1024,' GB')  AS CURRENT_NUMBER_OF_GB_USED,SUM_NUMBER_OF_BYTES_ALLOC from performance_schema.memory_summary_by_host_by_event_name order by CURRENT_NUMBER_OF_BYTES_USED  desc limit 10;

--统计用户消耗内存,如果SUM_NUMBER_OF_BYTES_ALLOC为零就代表没开启统计
select USER, EVENT_NAME, concat(CURRENT_NUMBER_OF_BYTES_USED/1024/1024/1024,' GB')  AS  CURRENT_NUMBER_OF_GB_USED, SUM_NUMBER_OF_BYTES_ALLOC from performance_schema.memory_summary_by_user_by_event_name order by CURRENT_NUMBER_OF_BYTES_USED  desc limit 10;

如何排查MySQL 内存泄漏

show engine innodb status\G;
-- 开启收集内存的统计信息
use performance_schema;
UPDATE setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'memory/%';
select event_name, current_alloc, high_alloc from sys.memory_global_by_current_bytes where current_count > 0 limit 10;
-- 
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(event_name, '/', 2), '/', -1) AS event_type, ROUND(SUM(CURRENT_NUMBER_OF_BYTES_USED)/1024/1024, 2) AS MB_CURRENTLY_USED 
FROM performance_schema.memory_summary_global_by_event_name 
GROUP BY event_type 
HAVING MB_CURRENTLY_USED > 0;

MySQL 内存占用分析 | Joe's Blog

观察到 MySQL 内存占用一直在上升,尽管到达了innodb_buffer_pool_size的内存上限,依然持续上涨,就算没有请求了,内存也只是维持不变,并不会下降。

技术分享 | MySQL 内存管理初探_ActionTech的博客-CSDN博客

MySQL实际占用物理内存比InnoDB_Buffer_Pool高很多且不释放,多占用的内存大多被内存分配器占用,为了高效管理内存,内存分配器通常会占用很多内存不释放;内存分配器不会永远不释放内存,需要达到某个阈值,释放一部分内存给操作系统;

MySQL 8.0.28 新功能 | MySQL 8.0不再担心被垃圾SQL搞爆内存 - 墨天轮

-- global_connection_memory_tracking
show global status like 'Global_connection_memory';
select @@global.connection_memory_limit;

数据库内存管理遇到的麻烦事儿,今天给一点解法 - 墨天轮
mysql查询库大小,表行数,索引大小
查看mysql库大小,表大小,索引大小

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,692评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,482评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,995评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,223评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,245评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,208评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,091评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,929评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,346评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,570评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,739评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,437评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,037评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,677评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,833评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,760评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,647评论 2 354

推荐阅读更多精彩内容