有哪些数据库内存知识点
本篇内容介绍了“有哪些数据库内存知识点”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
一、如何看懂内存指标遇到内存问题,可以先通过free、vmstat、top等命令,进行检查。free命令,可以获取系统内存的总体使用情况;vmstat命令,可以实时观察内存的变化情况;top命令,可以进行排序,获取内存占用大的进程。这里简单介绍一下free命令输出(以CentOS 7为例):
totalusedfreesharedbuff/cacheavailableMem:8008704523487615792064026159082467292Swap:204702047
第一行是内存数据
1. total:内存总大小,对应于/proc/meminfo的MemTotal
2. used:已使用的内存大小,对应于/proc/meminfo的(MemTotal - MemFree - Buffers - Cached - Slab)
3. free:未使用的内存大小,对应于/proc/meminfo的MemFree
4. buff/cache:已使用的缓存大小,对应于/proc/meminfo的Buffers+Cached
5. available:可供使用的内存大小,这是一个预估值,对应于/proc/meminfo的MemAvailable
第二行是交换分区数据
1. total:交换分区总大小,对应于/proc/meminfo的SwapTotal
2. used:已使用的交换分区,对应于/proc/meminfo的(SwapTotal - SwapFree)
3. free:未使用的的内存大小,对应于/proc/meminfo的SwapFree
这里值得注意的是,Linux操作系统会最大限度利用内存,空闲内存free少,不代表系统内存不够用了。个人建议,一方面需要观察内存增长的整体趋势是否逐渐趋于平稳、以及used和buff/cache的变化情况;另一方面需要观察是否频繁使用到交换分区swap,当然了,这里要避免NUMA和swapiness设置不正确带来的干扰。
二、MySQL如何使用内存在MySQL中,内存占用主要包括以下几部分,全局共享的内存、线程独占的内存、内存分配器占用的内存,具体如下:
全局共享
1. innodb_buffer_pool_size:InnoDB缓冲池的大小
2. innodb_additional_mem_pool_size:InnoDB存放数据字典和其他内部数据结构的内存大小,5.7已被移除
3. innodb_log_buffer_size:InnoDB日志缓冲的大小
4. key_buffer_size:MyISAM缓存索引块的内存大小
5. query_cache_size:查询缓冲的大小,8.0已被移除
线程独占
1. thread_stack:每个线程分配的堆栈大小
2. sort_buffer_size:排序缓冲的大小
3. join_buffer_size:连接缓冲的大小
4. read_buffer_size:MyISAM顺序读缓冲的大小
5. read_rnd_buffer_size:MyISAM随机读缓冲的大小、MRR缓冲的大小
6. tmp_table_size/max_heap_table_size:内存临时表的大小
7. binlog_cache_size:二进制日志缓冲的大小
内存分配器
在MySQL中,buffer pool的内存,是通过mmap()方式直接向操作系统申请分配;除此之外,大多数的内存管理,都需要经过内存分配器。为了实现更高效的内存管理,避免频繁的内存分配与回收,内存分配器会长时间占用大量内存,以供内部重复使用。关于内存分配器的选择,推荐使用jemalloc,可以有效解决内存碎片与提升整体性能。
因此,MySQL占用内存高的原因可能包括:innodb_buffer_pool_size设置过大、连接数/并发数过高、大量排序操作、内存分配器占用、以及MySQL Bug等等。一般来说,在MySQL整个运行周期内,刚启动时内存上涨会比较快,运行一段时间后会逐渐趋于平稳,这种情况是不需要过多关注的;如果在稳定运行后,出现内存突增、内存持续增长不释放的情况,那就需要我们进一步分析是什么原因造成的。
三、到底是谁占用了内存在绝大多数情况下,我们是不需要花费过多精力,去关注MySQL内存使用情况的;但是,也不能排除确实存在内存占用异常的情况,这个时候我们应该如何去进行深入排查呢?其实,MySQL官方就提供了强大的实时监控工具——performance_schema库下的监控内存表,通过这个工具,我们可以很清晰地观察到MySQL内存到底是被谁占用了、分别占用了多少。
开启内存监控
实例启动时开启
我们可以选择,在实例启动时,开启内存监控采集器,具体方法如下:
vimy.cnfperformance-schema-instrument='memory/%=ON'
禁用方法如下:
vimy.cnfperformance-schema-instrument='memory/%=OFF'
实例运行时开启
我们也可以选择,在实例运行时,动态开启内存监控采集器,具体方法如下:
mysql>UPDATEperformance_schema.setup_instrumentsSETENABLED='YES'WHERENAMELIKE'memory/%';
禁用方法如下:
mysql>UPDATEperformance_schema.setup_instrumentsSETENABLED='NO'WHERENAMELIKE'memory/%';
因为采集器的实现原理,是在内存进行分配/回收时,更新相对应内存监控表的数据;换句话说,就是采集器只能监控到开启之后的内存使用情况;而MySQL很大一部分内存都是在实例启动时就预先分配的,因此要想准确监控实例的内存使用率,需要在实例启动时就开启内存采集器。
内存监控表
在performance_schema库下,提供多个维度的内存监控表,具体如下:
memory_summary_by_account_by_event_name:账号纬度的内存监控表
memory_summary_by_host_by_event_name:主机纬度的内存监控表
memory_summary_by_thread_by_event_name:线程维度的内存监控表
memory_summary_by_user_by_event_name:用户纬度的内存监控表
memory_summary_global_by_event_name:全局纬度的内存监控表
内存监控表均包括以下关键字段:
COUNT_ALLOC:内存分配次数
COUNT_FREE:内存回收次数
SUM_NUMBER_OF_BYTES_ALLOC:内存分配大小
SUM_NUMBER_OF_BYTES_FREE:内存回收大小
CURRENT_COUNT_USED:当前分配的内存,通过COUNT_ALLOC-COUNT_FREE计算得到
CURRENT_NUMBER_OF_BYTES_USED:当前分配的内存大小,通过SUM_NUMBER_OF_BYTES_ALLOC-SUM_NUMBER_OF_BYTES_FREE计算得到
LOW_COUNT_USED:CURRENT_COUNT_USED的最小值
HIGH_COUNT_USED:CURRENT_COUNT_USED的最大值
LOW_NUMBER_OF_BYTES_USED:CURRENT_NUMBER_OF_BYTES_USED的最小值
HIGH_NUMBER_OF_BYTES_USED:CURRENT_NUMBER_OF_BYTES_USED的最大值
接下来,让我们看一个正常运行实例的内存使用情况,具体如下:
mysql>selectUSER,HOST,EVENT_NAME,COUNT_ALLOC,COUNT_FREE,CURRENT_COUNT_USED,SUM_NUMBER_OF_BYTES_ALLOC,SUM_NUMBER_OF_BYTES_FREE,CURRENT_NUMBER_OF_BYTES_USEDfromperformance_schema.memory_summary_by_account_by_event_nameorderbyCURRENT_NUMBER_OF_BYTES_USEDdesclimit10;+------+-----------+----------------------------+-------------+------------+--------------------+---------------------------+--------------------------+------------------------------+|USER|HOST|EVENT_NAME|COUNT_ALLOC|COUNT_FREE|CURRENT_COUNT_USED|SUM_NUMBER_OF_BYTES_ALLOC|SUM_NUMBER_OF_BYTES_FREE|CURRENT_NUMBER_OF_BYTES_USED|+------+-----------+----------------------------+-------------+------------+--------------------+---------------------------+--------------------------+------------------------------+|NULL|NULL|memory/innodb/buf_buf_pool|32|0|32|4500488192|0|4500488192||NULL|NULL|memory/innodb/os0event|1573559|0|1573559|214004024|0|214004024||NULL|NULL|memory/innodb/hash0hash|82|6|76|397976480|227067024|170909456||NULL|NULL|memory/innodb/log0log|10|0|10|33565840|0|33565840||root|localhost|memory/innodb/std|3650638|3043111|607527|160778066|141334898|19443168||NULL|NULL|memory/mysys/KEY_CACHE|3|0|3|8390768|0|8390768||NULL|NULL|memory/innodb/ut0pool|2|0|2|4194480|0|4194480||NULL|NULL|memory/innodb/sync0arr|3|0|3|2506184|0|2506184||NULL|NULL|memory/innodb/lock0lock|33|0|33|2245040|0|2245040||root|localhost|memory/innodb/mem0mem|9897784|9896793|991|8845389160|8843147749|2241411|+------+-----------+----------------------------+-------------+------------+--------------------+---------------------------+--------------------------+------------------------------+10rowsinset(0.01sec)
再看一个Bug #86821的场景,buffer pool占用最大内存正常,但是存储过程占用3GB就比较异常了,存在内存泄漏的风险;由此可知,通过内存监控表,我们可以快速定位内存异常占用问题。
mysql>selectevent_name,current_alloc,high_allocfrommemory_global_by_current_byteswherecurrent_count>0;+--------------------------------------------------------------------------------+---------------+-------------+|event_name|current_alloc|high_alloc|+--------------------------------------------------------------------------------+---------------+-------------+|memory/innodb/buf_buf_pool|7.29GiB|7.29GiB||memory/sql/sp_head::main_mem_root|3.21GiB|3.62GiB||memory/innodb/hash0hash|210.16MiB|323.63MiB||memory/sql/TABLE|183.82MiB|190.28MiB||memory/sql/Query_cache|128.02MiB|128.02MiB||memory/mysys/KEY_CACHE|64.00MiB|64.00MiB||memory/innodb/log0log|32.08MiB|32.08MiB||memory/innodb/parallel_doublewrite|30.27MiB|30.27MiB||memory/performance_schema/table_handles|27.19MiB|27.19MiB||memory/innodb/mem0mem|19.14MiB|20.79MiB||memory/performance_schema/events_statements_history_long|13.66MiB|13.66MiB||memory/performance_schema/events_statements_summary_by_digest.tokens|9.77MiB|9.77MiB|
另外,如果我们在内存监控表,看见一些比较陌生的event,可以翻阅官方文档或源码,继续进一步解读,例如
memory/innodb/os0event
/**@fileinclude/os0event.hTheinterfacetotheoperatingsystemconditionvariablesCreated2012-09-23SunnyBains(splitfromos0sync.h)*******************************************************/
memory/innodb/hash0hash
/**@fileinclude/hash0hash.hThesimplehashtableutilityCreated5/20/1997HeikkiTuuri*******************************************************/四、总结
总的来说,只要我们的操作系统/数据库有一个相对合理的配置(NUMA、swapiness、jemalloc、innodb_buffer_pool_size等等),大多数情况是不需要关注内存问题的;如果非常不幸运地碰到内存占用异常问题,可以通过官方提供的实时监控工具——内存监控表,快速进行定位;不过需要注意的是,开启内存采集器也会带来一些问题,比如额外的内存占用和性能损耗,一般建议是在系统出现内存问题之后,再重启实例启用,并等待复现。
“有哪些数据库内存知识点”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。