问题现象
使用 ResetConnection 协议,会话上出现内存堆积,将租户内存耗尽,业务 RT 升高。
关键诊断信息
触发条件
只要使用 ResetConnection 协议就会触发该问题。
Java 驱动使用接口 ((OceanBaseConnection)obc).reset(); 需要使用 OceanBase 特定版本驱动。
Python 驱动使用接口 cnx.cmd_reset_connection()。业务场景是 Python 驱动。
事前巡检
监控租户内存上涨情况,监控 SqlSession Label 的租户内存是否持续上涨。
事后诊断
执行如下查询 select * from oceanbase.__all_virtual_malloc_sample_info where tenant_id=xxx and mod_name= 'SqlSession' order by alloc_bytes desc limit 10; 如果能捞取到下面的内存申请栈,说明命中该问题。
oceanbase::common::light_backtrace(void**, int, long)
??:?
oceanbase::common::ModulePageAllocator::alloc(long, oceanbase::lib::ObMemAttr const&)
0_cxx.cxx:?
oceanbase::common::PageArena<char, oceanbase::common::ModulePageAllocator>::extend_page(long)
0_cxx.cxx:?
oceanbase::common::PageArena<char, oceanbase::common::ModulePageAllocator>::_alloc(long) [clone .cold.0]
0_cxx.cxx:?
oceanbase::sql::ObBasicSessionInfo::gen_sys_var_in_pc_str()
??:?
oceanbase::sql::ObBasicSessionInfo::init_system_variables(bool, bool, bool)
??:?
oceanbase::sql::ObBasicSessionInfo::reset_sys_vars()
??:?
oceanbase::observer::ObMPResetConnection::process()
??:?
oceanbase::omt::ObWorkerProcessor::process(oceanbase::rpc::ObRequest&)
0_cxx.cxx:?
oceanbase::omt::ObThWorker::worker(long&, long&, int&)
0_cxx.cxx:?
non-virtual thunk to oceanbase::omt::ObThWorker::run(long)
0_cxx.cxx:?
oceanbase::lib::Thread::__th_start(void*)
0_cxx.cxx:?

问题原因
ResetConnection 协议会重置当前连接上的一些信息,使链接恢复到一个初始状态。在重置的信息中,对 sys_var_in_pc_str 的值处理错误,仅重置了该值本身,没有释放值内存。导致这块的内存在每次重置之后都会堆积。
问题的风险及影响
长链接频繁调用 ResetConnection 协议,会话上出现内存堆积,可能耗尽租户内存。影响当前 Server 上其他请求的执行。
影响租户
影响 OceanBase 数据库中的 MySQL 租户,对于 SYS 租户和 Oracle 租户无影响
影响版本
OceanBase 数据库企业版 V4.3.3 GA(oceanbase-4.3.3.0-100000362024093001)及之后版本、V4.2.1 BP9(oceanbase-4.2.1.9-109000092024091919)及之后版本、V4.2.5 GA(oceanbase-4.2.5.0-100000082024102022)及之后版本、V4.3.5 GA(oceanbase-4.3.5.0-100000122024123020)及之后版本。
解决方法
升级至问题已修复版本。目前已修复的版本包括 OceanBase 数据库企业版 V4.2.1 BP10 Hotfix5(oceanbase-4.2.1.10-110050012025011614)、V4.2.5 BP1 Hotfix2(oceanbase-4.2.5.1-101020052025011421)、V4.2.5 BP2(oceanbase-4.2.5.2-102000122025011711)。
断连接或者重启内存膨胀的 Server 可恢复。
规避方式
用户可以梳理业务使用 ResetConnection 的场景,在业务侧避免使用该协议。
运维侧需要监控租户内存,如果检测到命中该场景,通过重启节点或者杀会话的方式进行规避。