首批通过分布式安全可靠测评,为关键业务系统打造
Nest Loop Join 场景存储层 core 问题
更新时间:2026-05-14 07:41
问题现象
Nest Loop Join 计划,core 在存储层。
关键诊断信息
触发条件
Nest Loop Join 计划,不断 rescan 右支的过程中,如果 rescan 只定位到一个微块,rescan 将右支的主键 range 传递到存储定位但后续没有读行,连续多次并且中间切换了微块,有可能触发存储层 core。
事前巡检
以下条件全部满足。
Nest Loop Join 计划。
NLJ 右支算子上有 startup_filter,这个就可能导致 rescan 将右支的主键 range 传递到存储定位但后续没有读行。
从 core 堆栈上大概率可以看到存储层
ObMicroBlockRowScanner::switch_range,也有可能是读微块数据堆栈。
事后诊断
满足上述 事前巡检 中的条件,再从 core 信息中看到。
ObSSTableRowScanner.ObSSTablePrefetcher.is_single_block_mode_是否 true。缓存了微块迭代器以及微块数据内存指针和微块 handle 里内存地址不对应。
基本可以判断为是这个问题。
问题原因
存储层对于 rescan 只定位到一个微块有一个优化,会在读行时把已经初始化好的微块迭代器以及微块数据内存指针保存下来,如果下一次 rescan 同样只定位到这个微块,可以直接复用微块迭代器。但在 rescan 只定位数据,但不读行的场景下存在问题。
第一次 rescan,定位到微块A,将A的数据放入到 kvcache 中,读行打开微块并且缓存了微块迭代器以及微块数据内存指针。
第二次 rescan,定位到微块B,没有读行,此时由于只有一个微块,使用了 1 中同样的微块 handle,导致微块A的引用被释放,内存可能被 kvcache 回收,由于没有读行,原来缓存的微块迭代器以及微块数据内存指针没有更新。
第三次 rescan,定位到了微块 A,如果微块A之前的内存被回收,那么会重新加载到内存,没有读行,原来缓存的微块迭代器以及微块数据内存指针没有更新。
第四次 rescan,定位到了 A,此时判断和上一次是同一个微块,复用了缓存的微块迭代器以及微块数据内存指针,访问了非法内存。
问题的风险及影响
导致访问非法内存,进程 core 掉。
影响租户
影响 OceanBase 数据库中的 SYS 租户和 Oracle 租户以及 MySQL 租户。
影响版本
OceanBase 数据库企业版 V3.2.2 GA(oceanbase-3.2.2-20211130225726)及之后版本、V3.2.3 GA(oceanbase-3.2.3.0-20220419)及之后版本、V3.2.4 GA(oceanbase-3.2.4.0-100000072022102819)及之后版本。
解决方法
升级至问题已修复版本。目前已修复的版本包括 OceanBase 数据库企业版 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 BP10 Hotfix20(oceanbase-3.2.3.3-110200012025111317)、V3.2.3 BP11(oceanbase-3.2.3.3-111000032024070822)、V3.2.4 BP8 Hotfix2(oceanbase-3.2.4.8-108020012024081520)、V3.2.4 BP8 Hotfix3(oceanbase-3.2.4.8-108030012024102211)。
- 可以尝试通过调整计划避免 NLJ。
规避方式
无 。