首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >OceanBase 租户内存爆了?看我如何进行根因定位!

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

作者头像
爱可生开源社区
发布2025-07-26 12:47:38
发布2025-07-26 12:47:38
2220
举报
作者:李富强,爱可生 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 的内存占用最大,接近租户的内存使用限制了。

代码语言:javascript
复制
# 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 内存分配的相关的关键信息,请继续往下看。

代码语言:javascript
复制
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 系统架构下查询。

代码语言:javascript
复制
select * from oceanbase.__all_virtual_malloc_sample_info where mod_name='SqlSessionSbloc' order by alloc_bytes DESC ;

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

代码语言:javascript
复制
# 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 了),升级后租户内存爆的问题解决。

代码语言:javascript
复制
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 #故障分析

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-07-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 爱可生开源社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 背景
    • 1.1 现象描述
    • 1.2 环境信息
  • 2. 故障诊断
    • 2.1 获取报错 SQL 的 TRACE_ID
    • 2.2 根据 TRACE_ID 过滤详细日志
    • 2.3 查看租户中各个上下文内存的占用
    • 2.4 查看指定上下文中各个 mod 内存的占用
    • 2.5 诊断内存模块内存消耗持续增长的问题
    • 2.6 查询指定 mod 的内存分配信息
    • 2.7 将采集到的分配内存的 back trace 转换为堆栈
    • 2.8 查看代码进一步确认
    • 2.9 故障解决
  • 3. 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档