检查mysql内存使用率_MySQL查看线程内存占用情况

1.背景

内存使用情况,决定着MySQL的性能,内存使用率过高会使系统响应时间变长,严重时内存耗尽还会出现OOM的情况。

2.资源检查

在操作系统层面,可以通过free命令查看系统内存资源使用情况,通过top -c命令查看进程使用内存占用情况。

root:~# free -mt

total used free shared buff/cache available

Mem: 16046 14928 201 13 917 753

Swap: 0 0 0

Total: 16046 14928 201

free命令显示内存占用情况:

总内存: 16046MB ≈ 16GB

已用内存: 14928MB ≈ 14.9GB

可用内存: free + buff/cache = 1118MB ≈ 1.1GB

即可用内存比例: 1.1GB / 16GB = 6.8%,通常我们系统监控内存低于10%就会告警。

查看系统进程,检查内存占用情况。

top - 16:11:01 up 71 days, 7:23, 1 user, load average: 0.09, 0.07, 0.20

Tasks: 188 total, 1 running, 187 sleeping, 0 stopped, 0 zombie

%Cpu(s): 2.1 us, 0.6 sy, 0.0 ni, 97.2 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

KiB Mem : 16431688 total, 208716 free, 15291936 used, 931036 buff/cache

KiB Swap: 0 total, 0 free, 0 used. 766408 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND

6626 mysql 20 0 16.064g 0.014t 6436 S 12.0 91.0 66694:13 /usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql --datadir=/data/mysql --plugin-dir=/usr/local/mysql/lib/plugin --user=mysq+

通过top -c命令发现mysql进程占用内存%MEM (91.0%),接下来检查下mysql是哪些线程和事件占用较高内存的。 首先检查实例的共享内存分配情况几个参数配置:

共享内存

mysql> select VARIABLE_NAME, VARIABLE_VALUE, concat(VARIABLE_VALUE/1024/1024,' MB') AS VARIABLE_VALUE_MB from information_schema.SESSION_VARIABLES where variable_name in ('innodb_buffer_pool_size','innodb_log_buffer_size','innodb_additional_mem_pool_size','key_buffer_size','query_cache_size');

+-------------------------+----------------+-------------------+

| VARIABLE_NAME | VARIABLE_VALUE | VARIABLE_VALUE_MB |

+-------------------------+----------------+-------------------+

| KEY_BUFFER_SIZE | 33554432 | 32 MB |

| QUERY_CACHE_SIZE | 1048576 | 1 MB |

| INNODB_LOG_BUFFER_SIZE | 67108864 | 64 MB |

| INNODB_BUFFER_POOL_SIZE | 10737418240 | 10240 MB |

+-------------------------+----------------+-------------------+

4 rows in set, 1 warning (0.00 sec)

检查了Innodb buffer的内存参数设置值10240MB = 10G, 占总内存 10G/16GB = 62.5%,该值设置在合理的范围内,详细的参数介绍可以参考官方文档,当系统内存严重不足时, 快速恢复可以降低共享内存,调整该参数后,内存会立马释放:

mysql> set global innodb_buffer_pool_size=8589934592;

Query OK, 0 rows affected (0.00 sec)

mysql> select VARIABLE_NAME, VARIABLE_VALUE, concat(VARIABLE_VALUE/1024/1024,' MB') AS VARIABLE_VALUE_MB from information_schema.SESSION_VARIABLES where variable_name in ('innodb_buffer_pool_size','innodb_log_buffer_size','innodb_additional_mem_pool_size','key_buffer_size','query_cache_size');

+-------------------------+----------------+-------------------+

| VARIABLE_NAME | VARIABLE_VALUE | VARIABLE_VALUE_MB |

+-------------------------+----------------+-------------------+

| KEY_BUFFER_SIZE | 33554432 | 32 MB |

| QUERY_CACHE_SIZE | 1048576 | 1 MB |

| INNODB_LOG_BUFFER_SIZE | 67108864 | 64 MB |

| INNODB_BUFFER_POOL_SIZE | 8589934592 | 8192 MB |

+-------------------------+----------------+-------------------+

4 rows in set, 1 warning (0.00 sec)

mysql> system free -mt

total used free shared buff/cache available

Mem: 16046 13020 2081 13 944 2666

Swap: 0 0 0

Total: 16046 13020 2081

这里我们为了快速释放系统内存,调整了INNODB_BUFFER_POOL_SIZE值后,可用内存恢复2G。

Session私有内存

共享内存中介绍的内存空间是实例创建时即分配的内存空间,并且是所有连接共享的。而出现 OOM 异常的实例通常都是由于下面各个连接私有的内存造成的。

mysql> select VARIABLE_NAME, VARIABLE_VALUE, concat(VARIABLE_VALUE/1024/1024,' MB') AS VARIABLE_VALUE_MB from information_schema.SESSION_VARIABLES where variable_name in ('read_buffer_size','read_rnd_buffer_size','sort_buffer_size','join_buffer_size','binlog_cache_size','tmp_table_size');

+----------------------+----------------+-------------------+

| VARIABLE_NAME | VARIABLE_VALUE | VARIABLE_VALUE_MB |

+----------------------+----------------+-------------------+

| SORT_BUFFER_SIZE | 33554432 | 32 MB |

| READ_RND_BUFFER_SIZE | 33554432 | 32 MB |

| READ_BUFFER_SIZE | 16777216 | 16 MB |

| BINLOG_CACHE_SIZE | 32768 | 0.03125 MB |

| TMP_TABLE_SIZE | 67108864 | 64 MB |

| JOIN_BUFFER_SIZE | 134217728 | 128 MB |

+----------------------+----------------+-------------------+

6 rows in set, 1 warning (0.00 sec)

这里的私有内存JOIN_BUFFER_SIZE=128MB, 默认值是256KB。用于普通索引扫描、范围索引扫描和不使用索引而执行全表扫描的联接的缓冲区的最小大小。通常获得快速连接的最佳方法是添加索引。在无法添加索引时,增加join_buffer_size的值,以获得更快的完全连接。为两个表之间的每个完整连接分配一个连接缓冲区。对于没有使用索引的几个表之间的复杂联接,可能需要多个联接缓冲区。

除非使用块嵌套循环或批处理键访问算法,否则设置大于保存每个匹配行所需的缓冲区不会有任何好处,并且所有连接至少分配最小的大小,因此在全局将该变量设置为大值时要小心。最好保持全局设置较小,只在执行大型连接的会话中将会话设置更改为较大的值。如果全局大小大于使用它的大多数查询所需要的大小,那么内存分配时间可能会导致显著的性能下降。

通过检查私有内存,我们发现这是的JOIN_BUFFER_SIZE全局设置较大。

内存监控

MySQL5.7版本通过performance_schema可以方便的查看内存占用情况, 前提是要打开监控,执行如下SQL语句,打开内存监控。

mysql> update performance_schema.setup_instruments set enabled = 'yes' where name like 'memory%';

mysql> select * from performance_schema.setup_instruments where name like 'memory%innodb%' limit 20;

+-------------------------------------------+---------+-------+

| NAME | ENABLED | TIMED |

+-------------------------------------------+---------+-------+

| memory/innodb/adaptive hash index | YES | NO |

| memory/innodb/buf_buf_pool | YES | NO |

| memory/innodb/dict_stats_bg_recalc_pool_t | YES | NO |

| memory/innodb/dict_stats_index_map_t | YES | NO |

| memory/innodb/dict_stats_n_diff_on_level | YES | NO |

| memory/innodb/other | YES | NO |

| memory/innodb/row_log_buf | YES | NO |

| memory/innodb/row_merge_sort | YES | NO |

| memory/innodb/std | YES | NO |

| memory/innodb/trx_sys_t::rw_trx_ids | YES | NO |

| memory/innodb/partitioning | YES | NO |

| memory/innodb/api0api | YES | NO |

| memory/innodb/btr0btr | YES | NO |

| memory/innodb/btr0bulk | YES | NO |

| memory/innodb/btr0cur | YES | NO |

| memory/innodb/btr0pcur | YES | NO |

| memory/innodb/btr0sea | YES | NO |

| memory/innodb/buf0buf | YES | NO |

| memory/innodb/buf0dblwr | YES | NO |

| memory/innodb/buf0dump | YES | NO |

+-------------------------------------------+---------+-------+

20 rows in set (0.00 sec)

该命令是在线打开内存统计,所以只会统计打开后新增的内存对象,打开前的内存对象不会统计,建议您打开后等待一段时间再执行后续步骤,便于找出内存使用高的线程。

内存相关表

这里我们查看performance_schema相关的内存监控表有哪些,分别可以统计哪些信息。

mysql> show tables like '%memory%';

+-----------------------------------------+

| Tables_in_performance_schema (%memory%) |

+-----------------------------------------+

| 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 |

+-----------------------------------------+

5 rows in set (0.00 sec)

以上表的监控统计,分别统计线程、帐户、用户、主机间接执行内存操作等信息,每个内存汇总表都有一个或多个分组列,用于指示表如何聚合事件,参考如下表介绍:表名说明

(一)统计事件消耗内存

mysql> select event_name, SUM_NUMBER_OF_BYTES_ALLOC from performance_schema.memory_summary_global_by_event_name order by SUM_NUMBER_OF_BYTES_ALLOC desc LIMIT 10;

+---------------------------------------+---------------------------+

| event_name | SUM_NUMBER_OF_BYTES_ALLOC |

+---------------------------------------+---------------------------+

| memory/sql/JOIN_CACHE | 966665202302976 |

| memory/memory/HP_PTRS | 304457132043176 |

| memory/innodb/mem0mem | 29273314618616 |

| memory/sql/thd::main_mem_root | 18376092762472 |

| memory/sql/Filesort_buffer::sort_keys | 3155343016712 |

| memory/sql/String::value | 2708659513792 |

| memory/sql/test_quick_select | 2146347475648 |

| memory/sql/QUICK_RANGE_SELECT::alloc | 1961041015680 |

| memory/mysys/IO_CACHE | 1463097599496 |

| memory/sql/TABLE | 635194922117 |

+---------------------------------------+---------------------------+

10 rows in set (0.01 sec)

注意到 “memory/sql/JOIN_CACHE” 消耗的内存最大。

(二)统计线程消耗内存

mysql> select thread_id, event_name, SUM_NUMBER_OF_BYTES_ALLOC from performance_schema.memory_summary_by_thread_by_event_name order by SUM_NUMBER_OF_BYTES_ALLOC desc limit 10;

+-----------+-----------------------+---------------------------+

| thread_id | event_name | SUM_NUMBER_OF_BYTES_ALLOC |

+-----------+-----------------------+---------------------------+

| 1922626 | memory/innodb/mem0mem | 1984233347055 |

| 1922439 | memory/innodb/mem0mem | 1404615671548 |

| 1954681 | memory/innodb/mem0mem | 1375641196768 |

| 1922431 | memory/innodb/mem0mem | 1350354644688 |

| 1954682 | memory/innodb/mem0mem | 1099479913383 |

| 1922625 | memory/innodb/mem0mem | 1097551130366 |

| 2686170 | memory/innodb/mem0mem | 992829979036 |

| 1922433 | memory/innodb/mem0mem | 874412348141 |

| 1922438 | memory/innodb/mem0mem | 863348539942 |

| 1922432 | memory/innodb/mem0mem | 754779357792 |

+-----------+-----------------------+---------------------------+

10 rows in set (0.02 sec)

上面统计结果发现到 “memory/innodb/mem0mem” 事件消耗的内存最多。

(三)统计账户消耗内存

mysql> select USER, HOST, EVENT_NAME, SUM_NUMBER_OF_BYTES_ALLOC from performance_schema.memory_summary_by_account_by_event_name order by SUM_NUMBER_OF_BYTES_ALLOC desc limit 10;

+-------------------+---------------+-----------------------+---------------------------+

| USER | HOST | EVENT_NAME | SUM_NUMBER_OF_BYTES_ALLOC |

+-------------------+---------------+-----------------------+---------------------------+

| c********** | 192.168.*.* | memory/sql/JOIN_CACHE | 638622579556352 |

| c********** | 192.168.*.* | memory/sql/JOIN_CACHE | 276949456912384 |

| b********** | 192.168.*.* | memory/memory/HP_PTRS | 166067384571544 |

| b********** | 192.168.*.* | memory/memory/HP_PTRS | 76145767762936 |

| b********** | 192.168.*.* | memory/sql/JOIN_CACHE | 42176612401152 |

| z********** | 192.168.*.* | memory/memory/HP_PTRS | 30219030003816 |

| s********** | 192.168.*.* | memory/innodb/mem0mem | 16114310343537 |

| b********** | 192.168.*.* | memory/sql/JOIN_CACHE | 9070736048128 |

| c********** | 192.168.*.* | memory/innodb/mem0mem | 4787044880366 |

| a********** | 192.168.*.* | memory/memory/HP_PTRS | 4764584763968 |

+-------------------+---------------+-----------------------+---------------------------+

10 rows in set (0.16 sec)

这里把相关敏感信息脱敏了,从上面发现用户 c* 占用内存最大。 事件还是memory/sql/JOIN_CACHE

(四)统计主机消耗内存

mysql > select HOST, EVENT_NAME, SUM_NUMBER_OF_BYTES_ALLOC from performance_schema.memory_summary_by_host_by_event_name order by SUM_NUMBER_OF_BYTES_ALLOC desc limit 10;

+---------------+-------------------------------+---------------------------+

| HOST | EVENT_NAME | SUM_NUMBER_OF_BYTES_ALLOC |

+---------------+-------------------------------+---------------------------+

| 192.168.*.* | memory/sql/JOIN_CACHE | 681148560703488 |

| 192.168.*.* | memory/sql/JOIN_CACHE | 286124345917440 |

| 192.168.*.* | memory/memory/HP_PTRS | 166777472915704 |

| 192.168.*.* | memory/memory/HP_PTRS | 76851688652536 |

| 192.168.*.* | memory/memory/HP_PTRS | 30227900416896 |

| 192.168.*.* | memory/innodb/mem0mem | 16117796446781 |

| 192.168.*.* | memory/memory/HP_PTRS | 7457591548256 |

| 192.168.*.* | memory/innodb/mem0mem | 6596914688112 |

| 192.168.*.* | memory/sql/thd::main_mem_root | 5979929501808 |

| 192.168.*.* | memory/sql/thd::main_mem_root | 4795924383312 |

+---------------+-------------------------------+---------------------------+

10 rows in set (0.07 sec)

通过上面的主机,也能快速定位是哪台主机占用内存大,有必要时可以重启该主机的应用。

(五)统计用户消耗内存

mysql> select USER, EVENT_NAME, SUM_NUMBER_OF_BYTES_ALLOC from performance_schema.memory_summary_by_user_by_event_name order by SUM_NUMBER_OF_BYTES_ALLOC desc limit 10;

+-------------------+-------------------------------+---------------------------+

| USER | EVENT_NAME | SUM_NUMBER_OF_BYTES_ALLOC |

+-------------------+-------------------------------+---------------------------+

| c**************** | memory/sql/JOIN_CACHE | 915572036468736 |

| b**************** | memory/memory/HP_PTRS | 242213179169888 |

| b**************** | memory/sql/JOIN_CACHE | 51247348449280 |

| z**************** | memory/memory/HP_PTRS | 30225123465960 |

| b**************** | memory/memory/HP_PTRS | 21863256050496 |

| s**************** | memory/innodb/mem0mem | 16116655699153 |

| e**************** | memory/sql/thd::main_mem_root | 9554995144176 |

| c**************** | memory/innodb/mem0mem | 6360931505366 |

| a**************** | memory/memory/HP_PTRS | 4765617785408 |

| s**************** | memory/sql/thd::main_mem_root | 3074066885016 |

+-------------------+-------------------------------+---------------------------+

10 rows in set (0.06 sec)

找到问题事件或线程后,您可以排查业务代码和环境,解决内存高的问题。上面统计结果发现到 “memory/sql/JOIN_CACHE” 事件消耗的内存最大。调整全局JOIN_BUFFER_SIZE=32MB,再观察内存占用情况。

mysql> set global join_buffer_size=33554432;

Query OK, 0 rows affected (0.00 sec)

mysql> quit

mysql> select VARIABLE_NAME, VARIABLE_VALUE, concat(VARIABLE_VALUE/1024/1024,' MB') AS VARIABLE_VALUE_MB from information_schema.SESSION_VARIABLES where variable_name in ('read_buffer_size','read_rnd_buffer_size','sort_buffer_size','join_buffer_size','binlog_cache_size','tmp_table_size');

+----------------------+----------------+-------------------+

| VARIABLE_NAME | VARIABLE_VALUE | VARIABLE_VALUE_MB |

+----------------------+----------------+-------------------+

| SORT_BUFFER_SIZE | 33554432 | 32 MB |

| READ_RND_BUFFER_SIZE | 33554432 | 32 MB |

| READ_BUFFER_SIZE | 16777216 | 16 MB |

| BINLOG_CACHE_SIZE | 32768 | 0.03125 MB |

| TMP_TABLE_SIZE | 67108864 | 64 MB |

| JOIN_BUFFER_SIZE | 33554432 | 32 MB |

+----------------------+----------------+-------------------+

6 rows in set, 1 warning (0.00 sec)

mysql> select * from information_schema.processlist where COMMAND='sleep' and Time>1000 order by Time desc;

这里会话参数调整后,需同时调整/etc/my.cnf的配置,下次服务启动永久生效,另外之前连接的会话线程由于已分配了该buffer大小,调整后内存并不会马上释放。

完。

<think>好的,我现在要解决用户关于如何设置NCCL_BUFFSIZE的问题。首先,我需要回忆一下NCCL是什么,NCCL_BUFFSIZE的作用,以及相关的设置方法。 首先,NCCL是NVIDIA Collective Communications Library的缩写,主要用于多GPU之间的通信优化,特别是在深度学习训练中,比如使用多个GPU进行分布式训练时,NCCL能够高效地处理GPU之间的数据交换。NCCL_BUFFSIZE应该是指NCCL在通信过程中使用的缓冲区大小,这个参数的设置可能会影响通信的效率和性能。 接下来,我需要确定NCCL_BUFFSIZE的具体作用。缓冲区大小通常会影响数据传输的效率和延迟。较大的缓冲区可能提高吞吐量,但会增加内存占用;较小的缓冲区可能减少延迟,但可能导致更多的通信次数,影响整体效率。不过,我需要确认这个参数在NCCL中的具体影响,可能需要查阅NCCL的官方文档或者相关资料。 然后,用户可能是在进行多GPU训练时遇到了性能问题,想要通过调整NCCL_BUFFSIZE来优化。这时候需要了解如何设置这个环境变量,以及推荐的取值范围或者最佳实践。此外,还要考虑不同版本的NCCL是否有不同的默认值或行为变化。 根据我的记忆,NCCL有一些环境变量可以调整,比如NCCL_IB_DISABLE、NCCL_SOCKET_IFNAME等,但NCCL_BUFFSIZE可能并不是最常用的参数。可能需要确认是否存在这个环境变量,或者是否用户可能记错了名称,比如是否是NCCL_BUFFSIZE还是其他类似的变量,比如NCCL_SHM_DISABLE、NCCL_NSOCKS_PERTHREAD等。 如果确实存在NCCL_BUFFSIZE这个变量,我需要查找它的具体用法。例如,NCCL的缓冲区大小可能用于设置每次通信操作中使用的内存大小,影响数据分块传输的方式。较大的缓冲区可能减少通信次数,但会占用更多显存或内存,而较小的缓冲区可能适合小规模数据传输,但可能增加开销。 另外,还需要考虑硬件环境,比如使用的网络类型(InfiniBand、以太网等)、GPU型号、NCCL版本等,这些因素都可能影响最佳缓冲区大小的设置。例如,在高速网络下,较大的缓冲区可能更有效,而在低带宽网络中可能需要不同的调整。 如果官方文档中没有明确说明NCCL_BUFFSIZE,可能需要通过实验来测试不同值对性能的影响。例如,用户可以在运行训练脚本前设置不同的值,观察训练速度和资源使用情况的变化。比如,在Linux系统中,可以通过export NCCL_BUFFSIZE=4194304来设置,然后运行训练任务,比较不同设置下的吞吐量和延迟。 另外,可能需要注意,某些NCCL参数可能有默认值,且NCCL会自动根据系统配置进行调整,因此手动设置可能需要谨慎,避免导致性能下降。例如,过大的缓冲区可能导致内存不足,或者影响其他进程的性能。 总结来说,回答需要包括以下几点: 1. 确认NCCL_BUFFSIZE的作用和是否存在。 2. 解释缓冲区大小对通信性能的影响。 3. 提供设置方法(环境变量)。 4. 建议的调整策略和注意事项。 5. 可能的替代参数或相关环境变量。 同时,需要提醒用户,如果没有特别的需求,使用默认值可能是最佳选择,调整前应进行基准测试,并参考官方文档或社区的最佳实践。</think>NCCL_BUFFSIZE 是 NVIDIA Collective Communications Library (NCCL) 中用于控制通信缓冲区大小的环境变量,主要影响多 GPU 或跨节点分布式训练时的数据传输效率。以下是关键点: --- ### **1. 作用原理** - **缓冲区功能**:NCCL 在通信(如 AllReduce、Broadcast 等)时会分割数据为多个块,通过流水线方式传输。`NCCL_BUFFSIZE` 决定单个块的大小。 - **性能影响**: - **较大值**:减少通信次数,提高吞吐量,但可能增加内存占用和单次传输延迟。 - **较小值**:降低单次延迟,但可能增加通信频率,影响整体效率。 --- ### **2. 设置方法** 通过环境变量直接设置(单位:字节): ```bash # 示例:设置缓冲区为 4MB export NCCL_BUFFSIZE=4194304 ``` --- ### **3. 调优建议** - **默认行为**:NCCL 通常会自动选择合理的值,无需手动调整。 - **调整场景**: - 网络带宽极高(如 InfiniBand):尝试增大值(如 `8388608` 即 8MB)。 - 低带宽或高延迟网络:尝试减小值(如 `1048576` 即 1MB)。 - **实验验证**:通过基准测试(如 `nccl-tests`)对比不同值下的吞吐量。 ```bash # 运行 NCCL AllReduce 测试 ./build/all_reduce_perf -b 8M -e 8G -f 2 -g 8 ``` --- ### **4. 注意事项** - **内存限制**:过大的缓冲区可能导致 OOM,尤其是在多进程场景下。 - **版本兼容性**:不同 NCCL 版本可能对缓冲区策略有优化,建议升级到最新版本。 - **相关参数**: - `NCCL_NCHANNELS`:控制并行通信通道数。 - `NCCL_SOCKET_NTHREADS`:调整网络线程数。 --- ### **总结** 若无显著性能问题,**优先使用 NCCL 默认配置**。若需手动调整,建议通过系统性基准测试确定最优值。可参考 NVIDIA 官方文档:[NCCL Environment Variables](https://docs.nvidia.com/deeplearning/nccl/user-guide/docs/env.html)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值