问题现象
OceanBase 数据库升级至 V3.2.3 BP11 版本后,持续执行只读事务,事务管理器引用计数泄露随着执行只读事务的数量增加,当最终超过 2^30 次后,触发线程死循环陷入 hashmap 的某一段代码中,表现为 CPU 用满,业务请求无法被处理,TPS 跌 0。
关键诊断信息
触发条件
升级到问题版本后,只读事务持续执行一段时间积累到一定次数后可触发。
事前巡检
暂时没有日志和系统内部表可以观察泄露情况。
事后诊断
通过 stack 堆栈中若发现几乎所有租户工作线程都堆栈停留在 ob_hash_map 中的 retireState 相关堆栈处,则可以明确是此问题。
问题原因
原因是此版本中对 BUG 的修改引入在获取事务管理器登记只读事务数后,未将事务管理器的引用归还递减。这样在每次处理完成一个只读事务请求即造成引用计数泄露 1 次,当泄露次数逐步增加超过计数器的阈值时,即导致计数器溢出而成为负数,此时一些依赖引用计数的线程将会判断错误而不停重试,执行堆栈表现为挂在一个地方不停重试。
问题的风险及影响
一旦只读事务数执行累计超过一定的量而触发此 BUG,则造成无法提供服务,TPS 跌 0。
考虑到阈值为 2^30 次,假设 TPS 为 1000,则启动后 12 天即可触发此 BUG。TPS 不同则触发此 BUG 的时长不一样。
如果可以及时在溢出前进行重启则可以避免。
影响租户
影响 OceanBase 数据库中的 SYS 租户和 Oracle 租户以及 MySQL 租户。
影响版本
OceanBase 数据库企业版 V3.2.3 BP11(oceanbase-3.2.3.3-111000032024070822)及之后版本。
解决方法
升级至问题已修复版本。目前已修复的版本包括 OceanBase 数据库 V3.2.3 BP11 Hotfix1(oceanbase-3.2.3.3-111010012024081311)、V3.2.3 BP11 Hotfix2(oceanbase-3.2.3.3-111020032024101417)、V3.2.3 BP11 Hotfix3(oceanbase-3.2.3.3-111030042025011012)、V3.2.3 BP11 Hotfix4(oceanbase-3.2.3.3-111040012025072114)。
重启服务可以恢复。只需要重启 Leader 节点。
规避方式
考虑到阈值为 2^30 次,假设 TPS 为 1000,则启动后 12 天即可触发此 BUG。TPS 不同则触发此 BUG 的时长不一样。可以根据 TPS 的高低进行在触发 BUG 前重启服务来避免。