首批通过分布式安全可靠测评,为关键业务系统打造
OBServer 在编译含大量 SQL 语句的文本匿名块时 CPU 可能持续飙高且无法下降
更新时间:2026-05-29 08:46
问题现象
问题出现概率不高,已有的出现场景是将大量 SQL 语句包裹进匿名块再运行会有小概率出现。
如下示例,如果有此类包含大量 SQL 语句的匿名块高并发执行时,有可能会触发该问题。
BEGIN
-- 中间含数百条 SQL 语句
END;
当问题出现时,可以观察到 CPU 持续升高且不下降,使用 obstack 抓取堆栈后,可以看到大量线程阻塞在 llvm::sys::MutexImpl::acquire,且找不到任何线程持有这把锁。
一个典型的堆栈如下。
#0 0x00007fb518111bdd in __lll_lock_wait from /lib64/libpthread-2.22.so
#1 0x00007fb51810c86c in __GI___pthread_mutex_lock from /lib64/libpthread-2.22.so
#2 0x0000000010987dec in llvm::sys::MutexImpl::acquire() from /home/admin/oceanbase/bin/observer
#3 0x0000000010982068 in llvm::sys::DynamicLibrary::getPermanentLibrary(char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) from /home/admin/oceanbase/bin/observer
#4 0x000000000f345ff6 in oceanbase::jit::core::ObOrcJit::ObOrcJit(llvm::TargetMachine*, oceanbase::common::ObIAllocator&) from /home/admin/oceanbase/bin/observer
#5 0x000000000f367ad0 in oceanbase::jit::ObLLVMHelper::init() from /home/admin/oceanbase/bin/observer
#6 0x000000000786b84a in oceanbase::pl::ObPLCompileUnit::ObPLCompileUnit(oceanbase::sql::ObCacheObjType, oceanbase::lib::MemoryContext&) from /home/admin/oceanbase/bin/observer
#7 0x0000000007587d91 in oceanbase::pl::ObPLFunction::ObPLFunction(oceanbase::lib::MemoryContext&) from /home/admin/oceanbase/bin/observer
#8 0x00000000075872b9 in oceanbase::pl::ObPL::execute(oceanbase::sql::ObExecContext&, _ParseNode const*) from /home/admin/oceanbase/bin/observer
#9 0x000000000e730d4b in oceanbase::sql::ObAnonymousBlockExecutor::execute(oceanbase::sql::ObExecContext&, oceanbase::sql::ObAnonymousBlockStmt&) from /home/admin/oceanbase/bin/observer
如上堆栈有两个关键点,llvm::sys::MutexImpl::acquire() 和 oceanbase::sql::ObAnonymousBlockExecutor::execute。
其中:
llvm::sys::MutexImpl::acquire()代表申请锁。oceanbase::sql::ObAnonymousBlockExecutor::execute代表匿名块的执行。
当观察到 OBServer 中大量线程等待到这把锁上,基本可以断定编译卡住了。此时后续的所有 PL 编译都会卡住,甚至整个OBServer 会 hang 住无法继续处理请求,有可能因为 hang 住的线程、OBServer 占据着部分资源造成更大面积服务不可用甚至系统完全不可用的情况。
如果遇到该问题,建议留存好用于诊断的日志及现场(相关节点的 observer.log、obstack 及 processlit),对节点进行重启恢复。
关键诊断信息
触发条件
使用大量文本匿名块。
事前巡检
如果预判需要并发执行大量文本匿名块,且 OBServer 在受影响的版本上,可能会有触发此问题的风险。
事后诊断
通过 obstack 抓堆栈,分析有多个甚至大量线程栈是在执行匿名块(oceanbase::sql::ObAnonymousBlockExecutor::execut),且在 lvm::sys::DynamicLibrary::getPermanentLibrary 调用 llvm::sys::MutexImpl::acquire(),即命中此问题。 一旦命中该问题,请立即保存 obstack 和 observer.log(high CPU 的节点)并重启节点,尽快恢复节点可用性。并对留存的信息进行诊断。
问题原因
PL 并发编译可能触发 LLVM 层面的 Mutex 锁获取失败。
问题的风险及影响
当 Mutex 锁无法获取后,后续所有 PL 的编译都可能会卡死,表现为 CPU 飚高。用户工作线程可能会逐步耗尽。
影响租户
影响 OceanBase 数据库中的 Oracle 租户,对于 SYS 租户和 MySQL 租户无影响。
影响版本
OceanBase 数据库企业版 V2.2.77 GA(oceanbase-2.2.77-20210508211731)及之后版本、V3.1.2 GA(oceanbase-3.1.2-20210618150922)及之后版本、V3.2.3 GA(oceanbase-3.2.3.0-20220419)及之后版本、V3.2.4 GA(oceanbase-3.2.4.0-100000072022102819)及之后版本、V4.1.0 GA(oceanbase-4.1.0.0-100001122023040322)及之后版本、V4.2.1 GA(oceanbase-4.2.1.0-100000182023092722)及之后版本。
解决方法及规避方式
解决方法
升级到问题修复版本,目前已修复的版本包含 OceanBase 数据库企业版 V3.2.3 BP10 Hotfix4(oceanbase-3.2.3.3-110040022023110614)、V3.2.3 BP10 Hotfix5(oceanbase-3.2.3.3-110050012023112210)、V3.2.3 BP10 Hotfix6(oceanbase-3.2.3.3-110060012024011615)、V3.2.3 BP10 Hotfix7(oceanbase-3.2.3.3-110070012024012316)、V3.2.3 BP10 Hotfix8(oceanbase-3.2.3.3-110080012024022713)、V3.2.3 BP10 Hotfix9(oceanbase-3.2.3.3-110090012024041611)、V3.2.3 BP10 Hotfix10(oceanbase-3.2.3.3-110100012024042814)、V3.2.3 BP10 Hotfix11(oceanbase-3.2.3.3-110110032024052217)、V3.2.3 BP10 Hotfix12(oceanbase-3.2.3.3-110120012024060510)、V3.2.3 BP10 Hotfix13(oceanbase-3.2.3.3-110130012024061819)、V3.2.3 BP10 Hotfix14(oceanbase-3.2.3.3-110140012024082010)、V3.2.3 BP10 Hotfix15(oceanbase-3.2.3.3-110150012024102111)、V3.2.3 BP10 Hotfix16(oceanbase-3.2.3.3-110160012025021315)、V3.2.3 BP10 Hotfix17(oceanbase-3.2.3.3-110170012025032112)、V3.2.3 BP10 Hotfix18(oceanbase-3.2.3.3-110180012025060316)、V3.2.3 BP10 Hotfix19(oceanbase-3.2.3.3-110190022025082615)、V3.2.3 BP11(oceanbase-3.2.3.3-111000032024070822)、V3.2.4 BP7(oceanbase-3.2.4.7-107000012023113010)、V4.2.1 BP2(oceanbase-4.2.1.2-102010012023120119)。
重启 CPU 持续飙高的 OBServer 节点。
注意
因为编译线程已经持有了 SchemaGuard,可能导致异步刷新 Schema 僵死。因此遇到类似问题时请尽快重启。
规避方式
将仅含有大量 SQL 语句的文本匿名块改为使用 Multi Query 规避。
匿名块采用 PS 的方式执行。
业务可以尝试降低文本匿名块的并发执行数量。