You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MariaDB 10.11.5频繁内存耗尽问题排查求助

MariaDB 10.11.5内存耗尽问题排查指南

问题背景

我们的MariaDB 10.11.5服务器每隔几天就会出现内存耗尽情况,服务器采用Galera复制架构,通过ProxySQL实现故障转移与连接池功能。服务器总内存32GB,当前MariaDB已占用约24GB。此前怀疑默认malloc库存在内存泄漏,切换为tcmalloc gperftools 2.6.1后内存增长速度有所放缓,但仍会逐渐耗尽。

当前innodb_buffer_pool为默认值(调大后内存耗尽更快),连接池保持300个连接,按配置计算单个连接约占19MB,300个连接仅占5GB,即使按最大连接数883计算也仅为16.8GB,远低于当前24GB的占用量。需明确以下问题:

  • 连接内存的计算逻辑是否有误?
  • 连接实际占用内存是否远超预期?
  • 如何查看表缓存或线程缓存的内存占用量?
  • 是否是复制机制导致的内存异常?

配置信息

[mysqld]
performance_schema=ON
event_scheduler=ON

max_connections = 5000

# SSD推荐设置为0
innodb_flush_neighbors=0

# 不使用MyISAM索引时建议设小(默认1G)
key_buffer_size=10M

[mariadb]
log_error=/var/log/mysql/error_log.log
log_warnings=4
slow_query_log=1
long_query_time = 5
slow_query_log_file=/var/log/mysql/slow_query.log

# 缩短连接休眠时间
wait_timeout = 600

问题解答

1. 连接内存计算逻辑是否有误?

你的计算仅考虑了连接线程的基础内存开销,但MariaDB的内存占用是多组件叠加的,遗漏了大量关键消耗项:

  • InnoDB缓冲池(10.11.5版本中,32GB内存服务器的默认值约为8GB,需结合SHOW VARIABLES确认具体数值)
  • 表缓存、表定义缓存的内存开销
  • 排序缓存、连接缓存、临时表内存——这些是每个连接按需分配的,并非固定每个连接占用19MB
  • Galera复制相关的写集缓存、复制线程内存
  • Performance Schema、事件调度器等后台组件的内存占用

仅计算连接线程内存会严重低估实际总占用,你的计算逻辑存在明显遗漏。

2. 连接实际占用内存是否远超预期?

单个连接的内存开销并非固定值,取决于实际执行的SQL操作:

  • 若连接执行大表排序、无索引关联等操作,会按需分配sort_buffer_size、join_buffer_size,这些缓存会额外占用内存
  • 使用MEMORY引擎的临时表会占用tmp_table_size范围内的内存,频繁创建大内存临时表会瞬间拉高内存占用
  • 线程缓存中的空闲线程也会持续占用内存,即使连接处于空闲状态

可通过以下SQL查看每个线程的内存使用细节(需开启performance_schema):

SELECT 
  thread_id, 
  processlist_id, 
  processlist_user, 
  processlist_host, 
  SUM(current_alloc) AS total_memory
FROM performance_schema.memory_summary_by_thread_by_event_name
GROUP BY thread_id, processlist_id, processlist_user, processlist_host
ORDER BY total_memory DESC;

3. 如何查看表缓存或线程缓存的内存占用量?

表缓存相关内存

-- 查看表缓存内存占用
SELECT 
  SUM(current_alloc) AS table_cache_memory
FROM performance_schema.memory_summary_by_event_name
WHERE event_name LIKE '%table%cache%';

-- 查看表定义缓存内存占用
SELECT 
  SUM(current_alloc) AS table_def_cache_memory
FROM performance_schema.memory_summary_by_event_name
WHERE event_name LIKE '%table_definition_cache%';

同时可通过SHOW STATUS LIKE 'Open_tables'查看当前打开的表数量,SHOW VARIABLES LIKE 'table_open_cache'查看配置上限,若Open_tables接近或超过上限,会导致频繁打开/关闭表,间接增加内存碎片。

线程缓存相关内存

SELECT 
  SUM(current_alloc) AS thread_cache_memory
FROM performance_schema.memory_summary_by_event_name
WHERE event_name LIKE '%thread_cache%';

通过SHOW STATUS LIKE 'Threads_cached'可查看当前缓存的空闲线程数量,若数量过大(如超过几百),会占用大量闲置内存。

4. 是否是Galera复制机制导致的内存异常?

Galera复制确实会产生额外内存开销,需重点排查以下几点:

  • wsrep_provider_options中的gcache.size:Galera全局写集缓存,默认值可能为1GB,高写负载场景下会占用更多内存,若写集无法及时清理会导致内存堆积
  • wsrep_slave_threads与wsrep_applier_threads:复制线程与写集应用线程的数量,每个线程会占用类似普通连接的内存开销
  • 查看Galera状态变量,确认节点状态与复制健康度:
SHOW STATUS LIKE 'wsrep%';

重点关注wsrep_local_state_comment(节点状态是否正常)、wsrep_flow_control_paused(是否存在流控导致内存堆积)、wsrep_apply_oooe/wsrep_apply_oool(是否有应用延迟导致写集堆积)

若Galera节点处于分裂、延迟等异常状态,写集无法及时应用或清理,会导致内存持续增长。


额外排查建议

  1. 监控内存变化趋势:使用vmstat、top或Prometheus+Grafana等工具跟踪MariaDB内存占用的变化,定位是否在高峰负载、批量任务时段出现内存陡增
  2. 排查内存泄漏:使用gperftools的pprof工具生成不同时间点的内存快照,对比找出内存增长的核心来源
  3. 优化配置参数:
    • 降低max_connections(当前设为5000,远高于实际使用的883,会预留过多闲置内存)
    • 合理设置innodb_buffer_pool_size:给Galera、连接线程预留8-10GB内存后,剩余资源分配给缓冲池
    • 限制sort_buffer_size、join_buffer_size的大小,避免单个连接占用过多内存
  4. 分析慢查询日志:排查是否存在大量耗时、高内存占用的SQL(如大表排序、无索引关联),这类操作会导致临时内存缓存暴涨

内容的提问来源于stack exchange,提问作者Nate L

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 17:34:54