暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

OceanBase 租户内存爆了?看我如何进行根因定位!

73

作者:李富强,爱可生 DBA 团队成员,OBCE;熟悉 MySQL,OceanBase 等数据库,擅长数据库架构设计,故障诊断,性能优化;技术让生活更美好,欢迎沟通交流,共同进步。

爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

本文约 1500 字,预计阅读需要 8 分钟。



1. 背景

1.1 现象描述

用户反馈,应用访问 OceanBase 数据库时报错,报错内容为:ErrorCode = 4013, SQLState = HY001, Details = No memory or reach tenant memory limit
,重启 OBServer 后暂时恢复,但过一段时间又会报相同的错误。

1.2 环境信息

  • 数据库版本:企业版 4.3.3.1
  • 部署架构:2-2-2
  • 租户模式:MySQL

2. 故障诊断

2.1 获取报错 SQL 的 TRACE_ID

开发同学通过 ODC[1] 执行查询也报同样错误,在 ODC 的执行记录中可以直接看到 SQL 的 TRACE_ID 信息。

点击异常 SQL 的 TRACE_ID,会弹出如下界面,依次点击全链路诊断,鼠标移动到com_query_process
 右侧的蓝色耗时区域,会出现该 Span 的具体内容,其中节点字段,即为 SVR_IP(如下是本地环境举例说明)。

获取执行过的 SQL 或者黑屏执行的 SQL 的 TRACE_ID 和 SVR_IP 方法,请查看文末参考资料[2]

2.2 根据 TRACE_ID 过滤详细日志

根据报错的时间范围和 TRACE_ID,过滤 OBServer 日志,在 SVR_IP 节点(实际为:113 节点)过滤到了详细的报错内容,显示租户占用内存加上租户新申请内存超过租户内存限制(tenant_hold+alloc_size>tenant_limit
)。

#[OOPS]: alloc failed reason is that tenant memory has reached the upper limit(tenant_id: 1010, tenant_hold: 11595448320, tenant_limit: 11596411700, alloc_size: 2097152)

2.3 查看租户中各个上下文内存的占用

过滤 113 节点 的 OBServer 日志,查看 1010 租户 的各个上下文的内存使用,显示上下文 DEFAULT_CTX_ID
 的内存占用最大,接近租户的内存使用限制了。

# grep 'malloc_allocator.*tenant: 1010'  observer.log.20250522105401599 -A 20

2.4 查看指定上下文中各个 mod 内存的占用

过滤 113 节点 的 OBServer 日志,查看 1010 租户 的上下文 DEFAULT_CTX_ID中各个mod的内存使用,显示 SqlSessionSbloc 这个 mod 占用内存最大,几乎用了整个租户 80% 以上的内存。通过一段时间观测内存使用会持续增加,最终导致租户内存用满。

分析到这,我们已经定位到导致租户内存用满的 mod 是谁了。通过查阅官方文档,并没有看到对这个 mod 的介绍,但我们知道,从 4.1 版本开始,提供了虚拟表来记录 mod 内存分配的相关的关键信息,请继续往下看。

grep '1010 ctx_id=           DEFAULT_CTX_ID'   observer.log.20250522105401599  -A 10

2.5 诊断内存模块内存消耗持续增长的问题

从 OceanBase 4.1.0 版本开始,提供了 __all_virtual_malloc_sample_info 虚拟表[3],此虚拟表常态化记录内存分配相关的关键信息,当 OBServer 的某个模块分配内存超过 GB,基于此虚拟表的信息,通常有能力定位到问题的根因。

有关 __all_virtual_malloc_sample_info
 表的字段说明如下:

列明
类型
含义
svr_ip
varchar:MAX_IP_ADDR_LENGTH
IP 地址
svr_port
int
端口号
tenant_id
int
租户 ID
ctx_id
int
CTX ID
mod_name
varchar:OB_MAX_CHAR_LENGTH
模块名称
back_trace
varchar:DEFAULT_BUF_LENGTH
内存分配的堆栈
ctx_name
varchar:OB_MAX_CHAR_LENGTH
CTX 名称
alloc_count
int
内存分配次数
alloc_bytes
int
内存分配的总大小

2.6 查询指定 mod 的内存分配信息

注意:虚拟表 __all_virtual_malloc_sample_info
 只能在 sys
 租户和 x86_64 系统架构下查询。

select * from oceanbase.__all_virtual_malloc_sample_info where mod_name='SqlSessionSbloc' order by alloc_bytes DESC ;

2.7 将采集到的分配内存的 back trace 转换为堆栈

# addr2line -pCfe bin/observer 0x1f5951a0 0x788cfac 0x7ce43e0 0x7ce3a48 0x15111873 Oxf35e3e8 0x79304ee 0x792e9af 0x791e66b 0xf054727 Ox1f6509be

通过调用栈分析,直接调用内存分配的函数是 set_login_info
,怀疑内存泄漏发生在 oceanbase::sql::ObSQLSessionInfo::set_login_info
 函数中。

2.8 查看代码进一步确认

OceanBase 社区版是 MySQL 租户兼容模式,所以我们可以看开源代码进行问题确认。

打开 OceanBase 社区版[4],选择最新发布版本,通过 ObSQLSessionInfo 关键字,找到代码文件ob_sql_session_info.cpp
,点击进入。

切换查看方式为 Blame,通过关键字 set_login_info,搜索函数的代码变更记录。

打开包含 fix memory leak 的代码提交的链接,可以看到该 commit 修复了一个由于 OceanBase 内部在复用一个会话时,直接分配内存(而不是尝试复用已有的内存),导致了内存泄露问题(fix memory leak caused by calling set_login_info() when reusing a session
),并且可以看到该 Bug 在 4.3.5 及之后的版本被修复了。

PS:如果这里没有查到函数的 bug fixed,需要研发根据 set_login_info
 函数代码逻辑进一步分析内存泄露的原因。

2.9 故障解决

最后和研发团队确认后,对当前数据库版本进行了升级(建议升级到 v4.3.5)。

升级后,在业务租户进行查询(租户中内存占用排名靠前的 mod 中,找不到 SqlSessionSbloc 这个 mod 了),升级后租户内存爆的问题解决。

SELECT svr_ip,ctx_name,mod_name ,sum(hold) FROM oceanbase.__all_virtual_memory_info WHERE tenant_id = 1010 group by svr_ip,ctx_name,mod_name order by sum(hold) desc limit 10;

3. 总结

本文主要分享了当租户内存用满时,如何通过分析 OBServer 日志,找到引起租户内存用满的 mod,遇到 mod 的内存占用持续增长的情况,如何进一步结合代码进行问题根因的定位,希望对你有帮助。

参考资料
[1] 

开发者工具 ODC: https://www.oceanbase.com/product/odc

[2] 

获取 SQL 执行的 svr_ip、trace_id 的方法: https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000225641

[3] 

使用 __all_virtual_malloc_sample_info 诊断 OceanBase 数据库内存模块问题: https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000002393827

[4] 

社区版 Github 仓库地址: https://github.com/oceanbase/oceanbase/tree/v4.3.5_CE_BP2_HF1


本文关键字:#OceanBase #故障分析





带宽被 OBServer 备份 “榨干”,集群陷入 “无主” 危机
OBLogProxy 在 Binlog 模式下的故障案例解析
计算 OceanBase 可用 CPU 的核心逻辑


✨ Github:https://github.com/actiontech/sqle

📚 文档:https://actiontech.github.io/sqle-docs/

💻 官网:https://opensource.actionsky.com/sqle/

👥 微信群:请添加小助手加入 ActionOpenSource

🔗 商业支持:https://www.actionsky.com/sqle


文章转载自爱可生开源社区,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论