日切表场景下,数据同步组件缓存句柄时,高并发查询information_schema.COLUMNS导致租户内存满

【 使用环境 】生产环境
【 OB or 其他组件 】OceanBase-CE-3.1.4
【 使用版本 】OceanBase-CE-3.1.4
【问题描述】在生产环境中,我们有一套联机系统,前端联机数据库使用的是MySQL,每日零点时会进行日切表的操作,通过自研的数据同步工具实时讲数据同步到汇总历史库社区版的OceanBase,UAT环境试运行期间一切正常,正式投产上线后发现每天在联机库切表时,汇总历史库OceanBase CPU使用率会快速冲高,数分钟后回落,期间导致十几笔联机交易查询失败。
经过排查,发现是由于生产环境为了提高数据同步效率将数据同步组件的线程数设置得比较大,在日切表时,每个线程都会通过查询information_schema.COLUMNS这个视图获取表结构缓存起来,在并发较大的情况下,查询information_schema的视图会导致租户内存满(reach tenant memory limit)
我们这个日切场景下并发查询information_schema的代码逻辑,是沿用的MySQL之间同步数据的机制,看起来在OB数据同步场景的情况下需要适配改造。
【问题】在这里想跟各位社区的专家探讨下,对于这种需要高并发查询OB数据库中虚拟表或者主表为虚拟表的视图操作,有什么好的优化方案?

1 个赞

可以考虑降低冻结转储的百分比和提供可用于 MemStore 写入的比例。

1. memstore_limit_percentage

  • 该参数用于控制租户内存中可用于 MemStore 写入的比例,默认值为 50%,表示租户可使用的 MemStore 占其总可用内存的 50%。
  • 取值范围为 [1, 99],修改该参数无需重启 OBServer 即刻生效。

2. freeze_trigger_percentage

  • 该参数用于控制当 MemStore 内存使用量达到其上限的百分比时触发转储,默认值为 20%,表示当 MemStore 使用率超过 20% 时,就会触发转储。
  • 取值范围为 [1, 99],修改该参数无需重启 OBServer 即刻生效。

或者扩容租户内存

3 个赞

新增租户单元,或者租户配置单元调大。

2 个赞

感谢社区官方人员提供的解决思路。
个人还是有个疑问,上述思路看起来只是简单地应对了租户内存满的问题,有点头痛医头的意思。

方案一:提高Memstore的内存占比大小和降低冻结转储的百分比,看起来是为了租户解决写入速度过快出现memstore内存打满的现象,当前这个集群的写入在4K TPS左右,都是在业务低峰的日切表期间,高并发查询虚拟表导致的异常。调整 memstore_limit_percentagefreeze_trigger_percentage能够缓解因为高频查询虚拟表导致的内存报错异常吗?

方案二:目前的集群是采用observer独占物理机的形式进行部署,业务租户的内存180G,sys租户的内存20G,system_memory 20G;我个人理解应该是稍微降低一些业务租户的内存,将其扩容到sys租户上?或者以加节点的形似将sys租户独立部署到其他机器上,提高sys租户的规格,但这种扩容方案带来的开销比较大

为了避免异常带来的负面影响,同事采取了sys租户内存扩容+降低同步工具并发线程数结合的措施,连续观察了三天,切表期间的异常没有再出现。

我们内部也探讨了有两种彻底解决设想思路,一是修改数据同步工具获取表结构的方式,从查询information_schema.COLUMNS改为desc table的形式,目前正在和相关研发人员探讨可行性和改造方案;
二是试图找到查询OB虚拟表的优化方案,由于以往的开发经验都是基于单机式或分库分表的数据库,在适配OB这种原生分布式数据库的时候,不可避免还会遇到类似的问题。目前想到的还有针对类似ETL的工具,增加全局锁降低查询并发或多线程之间共享一次查询表结构的结果

2 个赞

你方案二里面为什么会提到去查sys租户的相关信息,你说的columns视图在业务租户里面也有啊。正常情况你查询业务租户相关的视图就行了,这样sys租户也不用扩容。
其次columns这个视图在并发场景下查起来有性能问题,直接查询oceanbase.__all_virtual_information_columns应该会好点

1 个赞

目前就是查的业务租户下的information_schema.COLUMNS,这个视图的基表就是oceanbase.__all_virtual_information_columns

1 个赞

其实还有个办法就是让应用那边改,做到只查询一次不就行了

1 个赞

增加全局锁降低查询并发或多线程之间共享一次查询表结构的结果
我在上面的回复里面已经提及了这种解决思路,这种修改确实可行,但需要评估数据同步工具改动的代码量;
同时我们发现有比较多的应用也习惯通过查询information_schema下面的视图来获取相关信息,也出现把OB集群查出异常的情况,这里抛出这个问题的目的一是探讨数据库组件侧是否存在可能优化的手段,或者说未来可能会考虑对这一块进行优化;二是给社区用户一个提醒,可能在OB的应用适配改造最佳实践或者使用指南中增加一条提示,希望应用开发方适应原生分布式数据库产品的特性,关注OB和单机MySQL使用的差异,不要高频查询information_schema的视图/表对象

2 个赞

这里其实我还没来得及从代码层面去分析,所以有些不严谨。
我目前的理解是,information_schema.COLUMNS视图的基表已经确定是oceanbase.__all_virtual_information_columns,因此我认为即便我是通过业务租户去查询COLUMNS视图,实际查询的压力还是给到了sys租户下的虚拟表。
数据同步应用接收到的’reach tenant memory limit’ 报错实际是sys租户的内存达到了上限,而不是把业务租户的内存给打爆了

2 个赞

这点我确实没想到,在3.x中就算是业务租户下的__all_virtual_information_schema表也是查sys租户,查了下__all_virtual_table好像真只有一张‘__all_virtual_information_schema’,
但是4.x中这种系统表在业务租户中是单独的了,这点倒是有改善 :joy:

1 个赞

OB V3版本看起来是的,所以在应急的时候,我们安排一线进行了同步工具线程数的调整,同时我们将物理机上保留的计算资源全部扩容给了SYS租户,应急处置后,没有再出现异常情况。
针对这个问题,我们还对生产和预发布环境中,所有使用了OB V3版本的应用SQL语句进行了梳理,发现一个很有意思的现象,当查询information_schema.COLUMNS的SQL语句使用了函数对字段进行处理的时候,在并发不高的时候,SQL响应耗时都会出现异常。
这里可以给社区的用户提个醒,在使用OB V3版本时候,应用在适配改造的过程中,要留意对information_schema查询操作,非必要不查询,如确有必要,一是降低查询频率及并发;二是查询语句中尽量不要使用函数进行处理。

针对OB4.x中,系统表在业务租户中是单独的,后面我们也会在V4版本上进行一个实际验证。

1 个赞

听起来像是 查询这个视图的时候引发 内存泄漏。有这个可能性,如果要深入分析,可以用 obdiag 在案发前后都收集一下信息。 这个过程会比较长。

业务端可以换一种做法,起一个线程在日切之前提前查一次 ob的视图写到业务表里,然后你的程序并发查询这个业务表就行了。
表结构变更毕竟都在运维的控制能力以内。

1 个赞