MySQL内存使用的监控开关和使用查看


参考文档:
https://brands.cnblogs.com/tencentcloud/p/11151
https://www.cnblogs.com/grasp/p/10306697.html

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()方式直接向操作系统申请分配;除此之外,大多数的内存管理,都需要经过内存分配器。一般情况下, MySQL 使用 glibc(ptmalloc) 作为默认的内存分配器
为了实现更高效的内存管理,避免频繁的内存分配与回收,内存分配器会长时间占用大量内存,以供内部重复使用。关于内存分配器的选择,推荐使用jemalloc,
可以有效解决内存碎片与提升整体性能。

因此,MySQL占用内存高的原因可能包括:innodb_buffer_pool_size设置过大、连接数/并发数过高、大量排序操作、内存分配器占用、以及MySQL Bug等等。
一般来说,在MySQL整个运行周期内,刚启动时内存上涨会比较快,运行一段时间后会逐渐趋于平稳,这种情况是不需要过多关注的;
如果在稳定运行后,出现内存突增、内存持续增长不释放的情况,那就需要我们进一步分析是什么原因造成的。

三、到底是谁占用了内存

在绝大多数情况下,我们是不需要花费过多精力,去关注MySQL内存使用情况的;但是,也不能排除确实存在内存占用异常的情况,这个时候我们应该如何去进行深入排查呢?其实,MySQL官方就提供了强大的实时监控工具——performance_schema库下的监控内存表,通过这个工具,
我们可以很清晰地观察到MySQL内存到底是被谁占用了、分别占用了多少。

默认情况下performance_schema只对performance_schema进行了内存开销的统计。根据你的MySQL安装代码区域可能包括performance_schema、sql、client、innodb、myisam、csv、memory、blackhole、archive、partition和其他。

查看innodb相关的内存监控是否开启,默认不开启

mysql> SELECT * FROM performance_schema.setup_instruments
    -> WHERE NAME LIKE '%memory%';
复制代码
+--------------------------------------------------------------------------------+---------+-------+
| NAME                                                                           | ENABLED | TIMED |
+--------------------------------------------------------------------------------+---------+-------+
| memory/performance_schema/mutex_instances                                      | YES     | NO    |
| memory/performance_schema/rwlock_instances                                     | YES     | NO    |
| memory/performance_schema/cond_instances                                       | YES     | NO    |
| memory/performance_schema/file_instances                                       | YES     | NO    |
| memory/performance_schema/socket_instances                                     | YES     | NO    |
| memory/performance_schema/metadata_locks                                       | YES     | NO    |
| memory/performance_schema/file_handle                                          | YES     | NO    |
| memory/performance_schema/accounts                                             | YES     | NO    |
| memory/performance_schema/events_waits_summary_by_account_by_event_name        | YES     | NO    |
| memory/performance_schema/events_stages_summary_by_account_by_event_name       | YES     | NO    |
| memory/performance_schema/events_statements_summary_by_account_by_event_name   | YES     | NO    |
| memory/performance_schema/events_transactions_summary_by_account_by_event_name | YES     | NO    |
| memory/performance_schema/memory_summary_by_account_by_event_name              | YES     | NO    |
| memory/performance_schema/events_stages_summary_global_by_event_name           | YES     | NO    |
| memory/performance_schema/events_statements_summary_global_by_event_name       | YES     | NO    |
| memory/performance_schema/memory_summary_global_by_event_name                  | YES     | NO    |
| memory/performance_schema/hosts                                                | YES     | NO    |
| memory/performance_schema/events_waits_summary_by_host_by_event_name           | YES     | NO    |
| memory/performance_schema/events_stages_summary_by_host_by_event_name          | YES     | NO    |
| memory/performance_schema/events_statements_summary_by_host_by_event_name      | YES     | NO    |
| memory/performance_schema/events_transactions_summary_by_host_by_event_name    | YES     | NO    |
复制代码
可以通过条件缩小范围:

复制代码
mysql> SELECT * FROM performance_schema.setup_instruments
       WHERE NAME LIKE '%memory/innodb%';
+-------------------------------------------+---------+-------+
| NAME                                      | ENABLED | TIMED |
+-------------------------------------------+---------+-------+
| memory/innodb/adaptive hash index         | NO      | NO    |
| memory/innodb/buf_buf_pool                | NO      | NO    |
| memory/innodb/dict_stats_bg_recalc_pool_t | NO      | NO    |
| memory/innodb/dict_stats_index_map_t      | NO      | NO    |
| memory/innodb/dict_stats_n_diff_on_level  | NO      | NO    |
| memory/innodb/other                       | NO      | NO    |
| memory/innodb/row_log_buf                 | NO      | NO    |
| memory/innodb/row_merge_sort              | NO      | NO    |
| memory/innodb/std                         | NO      | NO    |
| memory/innodb/trx_sys_t::rw_trx_ids       | NO      | NO    |


对所有可能的对象进行内存监控。因此,还需要做下面的设置:

mysql> update performance_schema.setup_instruments set enabled = 'yes' where name like 'memory%';
Query OK, 306 rows affected (0.00 sec)
Rows matched: 376  Changed: 306  Warnings: 0
但是这种在线打开内存统计的方法仅对之后新增的内存对象有效,重启数据库后又会还原设置:

如想要对全局生命周期中的对象进行内存统计,必须在配置文件中进行设置,然后重启:

[mysqld]
performance-schema-instrument='memory/%=COUNTED'

内存监控表
在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> select 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 from performance_schema.memory_summary_by_account_by_event_name order by CURRENT_NUMBER_OF_BYTES_USED desc limit 10;
+------+------+----------------------------+-------------+------------+--------------------+---------------------------+--------------------------+------------------------------+
| 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 |           1 |          0 |                  1 |                 137428992 |                        0 |                    137428992 |
| NULL | NULL | memory/innodb/log0log      |           9 |          0 |                  9 |                  33563240 |                        0 |                     33563240 |
| NULL | NULL | memory/mysys/KEY_CACHE     |           3 |          0 |                  3 |                   8390768 |                        0 |                      8390768 |
| NULL | NULL | memory/innodb/hash0hash    |          47 |          6 |                 41 |                  11611464 |                  6641280 |                      4970184 |
| NULL | NULL | memory/innodb/ut0pool      |           2 |          0 |                  2 |                   4194480 |                        0 |                      4194480 |
| NULL | NULL | memory/innodb/os0event     |       25148 |          0 |              25148 |                   3420128 |                        0 |                      3420128 |
| NULL | NULL | memory/innodb/os0file      |         159 |         19 |                140 |                   3829193 |                  1098569 |                      2730624 |
| NULL | NULL | memory/innodb/buf0dblwr    |           5 |          1 |                  4 |                   2147728 |                    32792 |                      2114936 |
| NULL | NULL | memory/innodb/mem0mem      |        1028 |        648 |                380 |                   1293135 |                   993830 |                       299305 |
| NULL | NULL | memory/innodb/lock0lock    |          33 |          0 |                 33 |                    170968 |                        0 |                       170968 |
+------+------+----------------------------+-------------+------------+--------------------+---------------------------+--------------------------+------------------------------+
10 rows in set (0.01 sec)

简单来说,就是可以根据用户、主机、线程、账号、全局的维度对内存进行监控。同时库sys也就这些表做了进一步的格式化,可以使得用户非常容易的观察到每个对象的内存开销:

复制代码
mysql> select event_name,current_alloc from sys.memory_global_by_current_bytes limit 10;
+-----------------------------------------------------------------------------+---------------+
| event_name                                                                  | current_alloc |
+-----------------------------------------------------------------------------+---------------+
| memory/performance_schema/events_statements_history_long                    | 13.66 MiB     |
| memory/performance_schema/events_statements_history_long.sqltext            | 9.77 MiB      |
| memory/performance_schema/events_statements_history_long.tokens             | 9.77 MiB      |
| memory/performance_schema/events_statements_summary_by_digest.tokens        | 9.77 MiB      |
| memory/performance_schema/table_handles                                     | 9.06 MiB      |
| memory/performance_schema/events_statements_summary_by_thread_by_event_name | 8.67 MiB      |
| memory/sql/String::value                                                    | 6.02 MiB      |
| memory/performance_schema/memory_summary_by_thread_by_event_name            | 5.62 MiB      |
| memory/performance_schema/events_statements_summary_by_digest               | 4.88 MiB      |
| memory/sql/TABLE                                                            | 4.35 MiB      |
+-----------------------------------------------------------------------------+---------------+

可以使用sys库下的memory_global_by_current_bytes表来查询相同的底层数据,该模式表显示了全局服务器内当前内存使用情况,按分配类型进行细分。

复制代码
mysql> SELECT * FROM sys.memory_global_by_current_bytes
       WHERE event_name LIKE 'memory/innodb/buf_buf_pool'\G
*************************** 1. row ***************************
       event_name: memory/innodb/buf_buf_pool
    current_count: 1
    current_alloc: 131.06 MiB
current_avg_alloc: 131.06 MiB
       high_count: 1
       high_alloc: 131.06 MiB
   high_avg_alloc: 131.06 Mi
四、总结

总的来说,只要我们的操作系统/数据库有一个相对合理的配置(NUMA、swapiness、jemalloc、innodb_buffer_pool_size等等),大多数情况是不需要关注内存问题的;如果非常不幸运地碰到内存占用异常问题,可以通过官方提供的实时监控工具——内存监控表,快速进行定位;不过需要注意的是,开启内存采集器也会带来一些问题,比如额外的内存占用和性能损耗,一般建议是在系统出现内存问题之后,再重启实例启用,并等待复现。

你可能感兴趣的:(android)