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服务器来说,还有其他的缓存区域,都占用一定的内存空间。如果内存不够,则考虑增加内存。