本文从源码角度分析了 OceanBase 压测中冻结阈值动态变化的原因,并给出运维建议。
作者:张乾
外星人2号,兼任五位喵星人的铲屎官。
本文来源:原创投稿
- 爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
背景
测试在用小租户进行压测时,注意到监控中触发内存冻结的阈值是动态变化的,现象如下:
- 非压测时: 冻结阈值表现为 OceanBase 官方文档说明的
memstore_limit_percentage * freeze_trigger_percentage所计算的值,约为 322MB。 - 压测时: 冻结阈值表现出不规律的降低,但没有出现升高的情况,即始终低于非压测时的 322MB。

为什么压测时该阈值会变化?接下来分析一下现象的原因。
环境信息
| 版本信息 | OceanBase_CE 4.1.0.0 |
| 租户规格 | unit 8C4G |
| memstore_limit_percentage | 50(默认值) |
| freeze_trigger_percentage | 20(默认值) |
sysbench 命令
sysbench /usr/share/sysbench/oltp_read_only.lua --mysql-host=x.x.x.x --mysql-port=42881 --mysql-db=sysbenchdb --mysql-user="sysbench@sysbench_tenant2" --mysql-password=sysbench --tables=10 --table_size=1000000 --threads=1024 --time=120 --report-interval=10 --db-driver=mysql --db-ps-mode=disable --skip-trx=on --mysql-ignore-errors=6002,6004,4012,2013,4016,1062 run
排查过程
确认监控采集的正确性
根据监控指标,在官方文档中找到采集 SQL 如下:
select /* MONITOR_AGENT */ con_id tenant_id, stat_id, value from v$sysstat, DBA_OB_TENANTS where stat_id IN (130002) and (con_id > 1000 or con_id = 1) and class < 1000
经过手动执行该 SQL 语句,观察到在压测过程中冻结阈值确实发生了变化,由此可以确认监控数据采集和展示并无错误。
通过源码查看冻结阈值的计算方式
上一步确认了 OceanBase 冻结阈值的确存在变化,接下来需要进一步查看源码,了解该阈值是如何计算出来的。
静态分析视图的数据来源
在源码 ${path_to_oceanbase}/src/share/inner_table/ob_inner_table_schema_def.py 中检索视图名称,找到该视图的定义如下:

可以看到查询视图 v$sysstat 实际上是查询虚拟表 __all_virtual_sysstat。
注意:在 OceanBase 中,虚拟表并不是实际的表,是内存数据结构映射成可以用 SQL 语句直接查询的“表”。
虚拟表有对应的类来进行处理。当查询视虚拟表时,会调用相应类的方法来获取所需的值,然后将其返回给前端。
在 ${path_to_oceanbase}/src/observer/virtual_table 路径下,可以找到和虚拟表同名的头文件和对应的代码实现:
- ob_all_virtual_sys_stat.h
- ob_all_virtual_sys_stat.cpp
其中定义了虚拟表 __all_virtual_sysstat 对应的类 ObAllVirtualSysStat。

通常,从方法 inner_get_next_row() 开始进行调用,沿着该方法的调用静态分析下去,最终找到获取冻结阈值的方法是 ObTenantFreezer::get_freeze_trigger_()。
动态调试验证数据来源
我这里使用 VSCode + gdb 来调试,在 ObTenantFreezer::get_freeze_trigger_() 方法设置一个断点,先起一个连接到 OBServer,再启动调试模式,然后手动执行上面的采集 SQL。
注意:在 OceanBase 中,有多个方法会调用
get_freeze_trigger_()方法,因此断点未必会命中手动执行的 SQL。需要通过显示的堆栈判断是否是采集 SQL 命中了断点;如果不是,继续点击 Continue,直至 SQL 命中断点。
另一种方式是在对应类 ObAllVirtualSysStat 下的方法里设置断点,这样在执行 SQL 后,将直接命中断点,然后可以逐步进行调试,直至达到 get_freeze_trigger_() 方法。这种方式也适用于静态分析代码时找不到所需方法的情况。
在堆栈信息中,可以通过 do_process() 方法下的 sql 参数看到执行的 SQL 内容,如下:

本文通过源码分析揭示了OceanBase在压力测试时,冻结阈值动态变化的原因,主要涉及到内存管理机制,特别是MemStore和kv_cache内存的占用情况。当其他内存模块占用增加时,冻结阈值会降低。建议运维人员在发现阈值变化时关注内存使用,避免影响业务。
最低0.47元/天 解锁文章
247

被折叠的 条评论
为什么被折叠?



