内存分配算法配置及查询
lsof -p `pidof mysqld` | grep -i malloc
返回空说明使用默认GLIBC内存分配算法
返回libtcmalloc_minimal说明使用GOOGLE的tcmalloc算法
返回libjemalloc说明使用jemalloc算法
若使用默认GLIBC内存分配算法,则可以查询下当前内存碎片化情况
gdb -ex "call (void) malloc_stats()" --batch -p $(pidof mysqld)
上述命令执行完成后,会将内存使用情况打印到 MySQL 错误日志
将上述输出存入临时文件 tmp_mem_malloc.txt ,计算分配给 MySQL 内存和 MySQL 使用内存如下:
awk '{if($1 == "system") total+=$NF; else if ($1 == "in") used+=$NF }END{print total/1024/1024/1024,used/1024/1024/1024}' tmp_mem_malloc.txt
total和used相差越大,说明内存碎片化越严重
内存buffer参数配置最大占用计算
select VARIABLE_NAME,VARIABLE_VALUE/1024/1024 "size_MB/num" from performance_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','sort_buffer_size','read_buffer_size','read_rnd_buffer_size','join_buffer_size','thread_stack','binlog_cache_size')
union all
select VARIABLE_NAME,VARIABLE_VALUE from performance_schema.global_variables where VARIABLE_NAME in ('max_connections');
内存已经OOM过问题诊断
dmesg -Tx | grep -i "oom"
dmesg -Tx | grep -i "Dec 25"
dmesg -Tx > dmesg.log.20221227
oom日志中的rss为程序实际使用物理内存,单位为4kB内存页,换算为GB=rss*4/1024/1024
内存管理优化
MySQL 8.0.28版本中引入的一个新特性,即监控和限制各个连接(会话)的内存消耗,以避免因执行低效SQL而消耗过多内存,从而减少被操作系统OOM(Out of Memory)kill的风险。
-
新特性引入:MySQL 8.0.28版本开始支持监控和限制每个连接的内存消耗。
-
系统选项设置:
global_connection_memory_tracking = 1
:开启全局或会话级别的内存消耗跟踪。Global_connection_memory
:系统状态变量,用于查看所有连接消耗的内存总量。
-
内存统计更新频率:
connection_memory_chunk_size
:控制内存统计更新频率,默认值为8KB。
-
内存使用限制:
connection_memory_limit
:定义每个会话连接可使用的内存上限,默认值极大,实际上等于没有限制。如果需要,可以调低这个值以限制内存使用。
-
SQL内存消耗评估:
- 通过调整
connection_memory_limit
的值,可以评估一条SQL可能消耗的内存量。如果SQL消耗的内存超过限制,连接会被关闭。
- 通过调整
-
内存释放:
- SQL执行完毕后,相应的内存会立即释放,只保留维持会话连接所需的基本内存。
-
权限与内存限制:
- 普通用户执行SQL受到内存使用上限的约束,而具有SUPER权限的用户(如root)则不受此限制。
-
性能影响:
connection_memory_chunk_size
设置得太小可能会频繁更新内存统计,影响系统性能;设置得太大则可能导致OOM问题。