OceanBase 压测时为什么冻结阈值在变化?

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

本文从源码角度分析了 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 删除分区注意事项 在 OceanBase 中删除分区时,需要注意多个关键点,以确保操作的安全性与稳定性。以下为详细说明: - **分区类型限制**:OceanBase 仅支持对 RANGE、LIST 类型的分区执行删除操作。对于 HASH 和 KEY 类型的分区,由于其分区数据是通过哈希算法自动分布的,因此不支持直接删除某个具体的分区。如果需要调整 HASH 分区的数量,可以通过 `COALESCE PARTITIONS` 来减少分区数,系统将自动合并数据[^1]。 - **主键与唯一键约束**:分区键必须是主键或唯一键的一部分,否则在执行分区删除操作时可能会导致约束冲突。例如,若某张表的主键未包含分区键,则无法进行分区操作。 - **数据一致性保障**:删除分区是一个不可逆操作,执行后该分区中的所有数据将被永久删除。因此,在删除前应确保该分区中不再有活跃的数据或事务。建议在操作前进行数据归档或迁移,避免数据丢失。 - **回收站机制与恢复能力**:OceanBase 提供了回收站机制,用于在执行 DROP 或 TRUNCATE 操作后临时保留被删除对象,以便恢复。删除分区操作可能会影响回收站中对象的状态,因此在删除前应了解当前租户对回收站的访问权限和管理范围。例如,SYS 租户可以管理系统内所有租户的回收站对象,而普通租户只能管理其所属租户的对象。 - **分区合并与重建**:对于二级分区(复合分区),如 RANGE-LIST 或 RANGE-HASH 类型,删除操作仅适用于一级分区,无法单独删除某个二级子分区。若需调整子分区结构,通常需要重建分区表。 - **统计信息更新**:删除分区后,建议执行 `ANALYZE TABLE` 操作以更新统计信息,确保查询优化器能够生成更优的执行计划。 - **操作前的验证与测试**:在生产环境中执行删除分区操作前,应在测试环境中进行充分验证,确保操作逻辑正确且不会影响业务连续性。 ### 示例:删除分区 ```sql -- 删除指定分区 ALTER TABLE sales DROP PARTITION p202201; -- 减少 HASH 分区数量 ALTER TABLE sales_hash PARTITION p1, p2, p3, p4 COALESCE PARTITIONS 2; ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值