87.MySQL服务器内存VIRT,RES,MEM%高问题排查

本文讨论了如何通过调整MySQL服务器的内存配置,如释放swap分区、清理缓存和调整INNODB缓冲池,来降低VIRT、RES和内存使用率。重点强调了物理内存的重要性以及内存不足时的处理策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.现象

VIRT=37G;

这个是虚拟内存的大小:包含innodb_buffer_pool_size+SWAP分区大小+Buffer/Cache大小

=20G+4.8G+15G=39.8G~近似等于VIRT:37G.

起初我们测试了,thread_cache_size的变化对于内存的影响,测试结果显示,thread_cache_size对MEM%内存的使用几乎没有影响。

2.分析

从截图来看,SWAP=4.8G,一般数据库在运行过程中使用的内存超过物理内存,则会使用SWAP分区,此时性能较差,速度慢。此时应该增加物理内存。

调整降低:MEM%的方法
1).释放swap分区空间
当前如果数据库在运行时,物理内存足够,则调整释放SWAP分区占用的空间。
Swapoff -a  --关闭swap分区,释放swap 
Swapon -a  --开启swap分区。
2)释放缓存区
echo 1 > /proc/sys/vm/drop_caches
3)清理innodb的脏页
Set global innodb_buffer_pool_size=NUMER1     --先调整为原来的一半
Set global innodb_buffer_pool_size=NUMER2     --再调整为原来大小 
此时VIRT,RES,内存均会变小。
SWAP USED=0,即SWAP分区的大小已经释放。
注:NUMBER1,NUMBER2是以字节计算的内存大小。

3.INNODB引擎分析

INNODB buffer pool有多个实例,数据页大概:1273192*16/1024=19.4G 
说明数据页已经全部用于缓存数据。所有内存已被充分利用。数据库所占用的页均已满了。
此时如果执行大的DML,则会导致RES内存增长,free命令:USED内存增长,buff/cache内存增长。除了free_min_kbytes 代表的保留内存,其他内存如果使用完毕,则会使用SWAP分区。整体上会导致VIRT,RES,SWAP内存的增长。

如果我们的系统允许大的事务的SQL运行,则时常监控SWAP分区的变化,如果SWAP分区使用较多,说明物理内存明显不足,需要增加物理内存。如果物理内存足够,且长期稳定,只是偶尔会有SWAP分区内存增长情况,不用关心VIRT内存高,因为根据数据库的内存使用机制和操作自身的内存使用机制。如果内存不足时会释放相关脏页,腾出新的内存使用。SWAP USED分区大,不代表每次运行时都使用到了SWAP分区,只是SWAP分区里面的脏数据没有被有效的清理而已。

4.MYSQL实际内存查询方法

(1)MySQL服务内存组成部分
MYSQL服务器使用的内存=
INNODB_BUFFER_POOL_SIZE+KEY_BUFFER_SIZE+
TMP_TABLE_SIZE +SORT_BUFFER_SIZE+
READ_BUFFER_SIZE+READ_RND_BUFFER_SIZE+
JOIN_BUFFER_SIZE+THREAD_STACK+BINLOG_CACHE_SIZE 


(2)MySQL服务器内存查询方法
先开器兼容性参数,再执行查询。
set global show_compatibility_56=on;
select VARIABLE_NAME,VARIABLE_VALUE/1024/1024 MB from information_schema.GLOBAL_VARIABLES WHERE VARIABLE_NAME in ('key_buffer_size','query_cache_size','tmp_table_size','innodb_buffer_pool_size','innodb_additional_mem_pool_size','innodb_log_buffer_size')
union all
SELECT 'sort_buffer_size',(V1.VARIABLE_VALUE*v2.vv) MB
FROM ( select VARIABLE_VALUE from information_schema.GLOBAL_VARIABLES WHERE VARIABLE_NAME='MAX_CONNECTIONS' ) AS v1,
  ( SELECT VARIABLE_VALUE/1024/1024 vv FROM information_schema.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'sort_buffer_size' ) AS v2 
union all
SELECT 'read_buffer_size',(V1.VARIABLE_VALUE*v2.vv) MB
FROM ( select VARIABLE_VALUE from information_schema.GLOBAL_VARIABLES WHERE VARIABLE_NAME='MAX_CONNECTIONS' ) AS v1,
  ( SELECT VARIABLE_VALUE/1024/1024 vv FROM information_schema.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'read_buffer_size' ) AS v2 
union all
SELECT 'read_rnd_buffer_size',(V1.VARIABLE_VALUE*v2.vv) MB
FROM ( select VARIABLE_VALUE from information_schema.GLOBAL_VARIABLES WHERE VARIABLE_NAME='MAX_CONNECTIONS' ) AS v1,
  ( SELECT VARIABLE_VALUE/1024/1024 vv FROM information_schema.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'read_rnd_buffer_size' ) AS v2 
union all
SELECT 'join_buffer_size',(V1.VARIABLE_VALUE*v2.vv) MB
FROM ( select VARIABLE_VALUE from information_schema.GLOBAL_VARIABLES WHERE VARIABLE_NAME='MAX_CONNECTIONS' ) AS v1,
  ( SELECT VARIABLE_VALUE/1024/1024  vv FROM information_schema.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'join_buffer_size' ) AS v2 
union all
SELECT 'thread_stack',(V1.VARIABLE_VALUE*v2.vv) MB
FROM ( select VARIABLE_VALUE from information_schema.GLOBAL_VARIABLES WHERE VARIABLE_NAME='MAX_CONNECTIONS' ) AS v1,
  ( SELECT VARIABLE_VALUE/1024/1024 vv FROM information_schema.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'thread_stack' ) AS v2 
union all
SELECT 'binlog_cache_size',(V1.VARIABLE_VALUE*v2.vv) MB
FROM ( select VARIABLE_VALUE from information_schema.GLOBAL_VARIABLES WHERE VARIABLE_NAME='MAX_CONNECTIONS' ) AS v1,
  ( SELECT VARIABLE_VALUE/1024/1024 vv FROM information_schema.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'binlog_cache_size' ) AS v2; 



(3)查询得到如下结果
+-----------------------------------------+--------+
| VARIABLE_NAME           | MB     |
+-----------------------------------------+--------+
| TMP_TABLE_SIZE           |     96 |
| KEY_BUFFER_SIZE           |    800 |
| QUERY_CACHE_SIZE        |      0 |
| INNODB_LOG_BUFFER_SIZE  |     64 |
| INNODB_BUFFER_POOL_SIZE |   4096 |
| sort_buffer_size           |   3000 |
| read_buffer_size           |   3000 |
| read_rnd_buffer_size       |  24000 |
| join_buffer_size           |   3000 |
| thread_stack              | 281.25 |
| binlog_cache_size         |   6000 |
+----------------------------------------+--------+
按照上面的公式进行计算,就可以得到mysql服务器占用的内存大小。即可以解释,为什么TOP 命令中VIRT,RES,MEM%资源高。Innodb_buffer_pool_size代表仅仅只是数据页的大小,对于MySQL服务器来说,还有其他的缓存区域,都占用一定的内存空间。如果内存不够,则考虑增加内存。

5.总结

先按如上方法,调整SWAP,cache,等的内存占用。降低VIRT,RES,MEM%等的内存,持续观察,看是否每次都会导致SWAP分区使用较多,如果是则增加物理内存。确保物理内存足够,确保不使用SWAP分区。Innodb_buffer_pool_size代表仅仅只是数据页的大小,对于MySQL服务器来说,还有其他的缓存区域,都占用一定的内存空间。如果内存不够,则考虑增加内存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值