OB_MEMSTORE 模块开启内存泄露检测没有信息的问题

【使用环境】调试环境

【ObServer】

【使用版本】3.1.5

【问题描述】

按照租户内存超限文档的介绍,检查 OB_MEMSTORE 模块内存泄露。

文档链接:https://www.oceanbase.com/docs/community-observer-cn-10000000000450197

操作步骤如下:

  1. ALTER system SET leak_mod_to_check=‘OB_MEMSTORE’;

  2. SELECT * FROM __all_virtual_mem_leak_checker_info ORDER BY alloc_count;

多次频繁查询,没有从 __all_virtual_mem_leak_checker_info 表中查询到所有信息。

经过调试代码,发现 ALTER system SET leak_mod_to_check=‘OB_MEMSTORE’ 使用的内存检查方式是 LABEL_CHECK。

但是只有通过 ObMallocAllocator::alloc() 方法申请内存,才会使用 LABEL_CHECK 方式进行内存泄露检查,而 OB_MEMSTORE 申请内存不会调用 ObMallocAllocator::alloc() 方法。

OB_MEMSTORE 会通过 ObTenantCtxAllocator::alloc() 方法申请内存,经过多级,会调用到 ObjectSet::alloc_object() 方法。

ObjectSet::alloc_object() 方法中会使用 CONTEXT_CHECK 方式进行内存泄露检查。

基于以上信息,有 2 个疑问:

  1. 问题一:OB_MEMSTORE 模块是否不能使用 LABEL_CHECK 方式进行内存泄露检查?

  2. ObjectSet::alloc_object() 方法部分代码如下:


AObject* ObjectSet::alloc_object(const uint64_t size, const ObMemAttr& attr)

{

uint64_t alloc_size = size;

auto& leak_checker = common::ObMemLeakChecker::get_instance();

// ObTenantCtxAllocator::alloc() 经过多级调用 ObjectSet::alloc_object() 方法时

// mem_context_ 一直都是 null,check_leak 就为 false

bool check_leak = mem_context_ != nullptr && leak_checker.is_context_check() &&

leak_checker.get_static_id() == mem_context_->get_static_id();

if (OB_UNLIKELY(check_leak)) {

alloc_size += BT_BUF_LEN;

}

...

// 因为 check_leak = false,所以不会使用 CONTEXT_CHECK 方式进行内存泄露检查

// 也就是说 OB_MEMSTORE 模块也不会使用内存泄露检查

check_leak = check_leak && (leak_checker.is_wildcard() || leak_checker.label_match(*obj));

if (OB_UNLIKELY(check_leak)) {

common::lbt(&obj->data_[alloc_size - BT_BUF_LEN], BT_BUF_LEN);

}

...

}

问题二:OB_MEMSTORE 模块也无法使用 CONTEXT_CHECK 方式进行内存泄露检查?

OB_MEMSTORE模块比较特殊,对于其内存泄露检测在3.1是存在BUG的。
具体来说是历史遗留问题,mod在3.1里源码里有两个类型,id和字符串,分别对应mod_id和label,而memleak这里是优先去匹配id,因为OB_MEMSTORE在mod跟label里重复定义了,所以把OB_MEMSTORE当成了mod_id在监控,但真实分配还是按字符串在用,这里就不匹配了。
该问题在4.x是通过部分重构解决了的。
另外,LABEL_CHECK和CONTEXT_CHECK并不影响memleak的检查。

1 个赞

收到,多谢镜水兄。
4.0 中已验证,可通过以下 2 步对 Memstore 模块进行内存泄露检查:

  • ALTER SYSTEM SET leak_mod_to_check = ‘Memstore’;
  • SELECT * FROM __all_virtual_mem_leak_checker_info;

模块名由 OB_MEMSTORE 变为 Memstore 了。