Schema 定义了数据库对象的逻辑结构,比如表的定义,字段的属性等。在创建、修改数据库对象的定义时,OceanBase 会创建对应的 Schema 版本,并保留旧的 Schema 版本。 OceanBase 提供相应的 Schema History 回收机制,来控制过期 Schema 版本的回收。
详细说明
回收机制
OceanBase 数据库会周期性地发起 Schema History 的清理任务,将满足条件的 Schema History 从相应的系统表(比如 __all_table_history 和 __all_column_history 以及 __all_ddl_operation 等)中删除。
需要注意的是,Schema History 的回收前提是对应的对象已经被删除。虽然 ALTER TABLE 也会形成 Table Schema 的多版本数据,但只有在 DROP TABLE 后 __all_table_history 中的多版本记录才会被删除。
Schema History 的回收机制主要由以下参数来控制,如下表格所示:
| 配置项 | schema_history_recycle_interval | schema_history_expire_time |
|---|---|---|
| 级别 | 集群级 | 集群级 |
| 默认值 | 10m | 7d |
| 取值范围 | [0s, +∞) | [1m, 30d] |
| 说明 | 设置 Schema History 回收任务的调度间隔,0 表示关闭回收功能,默认为 10 分钟一次。 | 设置 Schema History 的最大保留时间,默认为 7 天。 |
在 OceanBase 数据库 V4.x 版本,Schema 的管理由各个租户自身负责,不再由系统租户统一管理。因此,Schema History 的回收也由租户单独来调用。
问题场景
高频 DDL 操作导致 DML 出现性能问题
单表高频做 DDL(e.g. drop/create/truncate partition/subpartition)的场景,因为 Schama 所在的 Cache 被频繁地刷新,DML 执行获取历史版本 Schema 时会出现 Cache Miss,Schema 刷新的性能受到影响。
对单表,特别是在分区数目很多的表执行高频 DDL,可能出现以下两个问题:
Schema Cache 失效的情况下,获取多版本 Schema 的动作由于 Schema History 过多会很耗时增加。
转储时需要获取多版本数据对应的 Schema 版本。如果 Schema History 过多导致无法命中 Cache,会影响转储的性能,导致转储、合并的耗时变长,MemStore 内存无法及时释放,可能出现 MemStore 内存用满的问题。
以 OceanBase 数据库 V3.x 版本的一个实际问题场景为例,对一个分区表每分钟执行一次 Truncate Partition 操作。因为系统参数 schema_history_expire_time=30d,该表保留了 14W+ Schema History。因为 Schema History 信息过多,每次刷新 Schema 的耗时约为 400ms+。由于该表有 6000+分区,转储的时候调度一轮该表的所有分区的转储需要数小时,严重阻碍了转储的正常执行。
系统租户有规律地出现 CPU 使用冲高的现象
如果系统中频繁的执行 Schema 的变更操作(DDL),Schema History 的信息保留过多,那么在 Schema History 回收任务执行时查询、清理相应的 Schema History 表会性能变差,消耗大量的 CPU 资源,从而导致系统租户周期性地出现 CPU 使用量冲高的现象,如下图所示:

解决方法
方法一:减少 DDL 变更的次数
Schema History 的记录数与 DDL 变更的次数直接相关,如果存在一些频繁执行 DDL 变更的表,建议尽量将一个表上的多条 DDL 操作合并成一条 DDL,以减少 Schema History 的记录数。比如,将连续为一个表添加分区的多条 DDL 操作合并为一条同时添加多个分区的 DDL 操作。
方法二:调小 Schema History 的保存时间
Schema History 的保存历史越久,Schema History 清理线程需要扫描和清理的记录就越多。可以通过调小 schema_history_expire_time 的值,减少 Schema History 的保存周期,从而减少 Schema History 的记录数。
方法三:调大回收线程的调度间隔
回收线程会对所有过期的 Schema History 记录执行清理,理论上一次调用可以回收掉之前所有的过期记录。可以适当调大 schema_history_recycle_interval 的值,避免回收线程的频繁调用对租户的平稳运行造成影响。
方法四:调大内部 SQL 的超时时间
回收线程在执行回收操作前,需要查询相应的系统表(比如 __all_table_history 和 __all_column_history 以及 __all_ddl_operation 等),以确定待删除 Schema History 的记录范围。如果当前租户的 Schema History 记录太多,以至于执行查询的 SQL 发生执行超时,则本轮回收失败,会在下个周期重试。这样,就可能会导致超时失败--下轮重试的循环。针对这种场景,需要调大内部 SQL 的超时时间,命令如下:
ALTER SYSTEM SET internal_sql_execute_timeout='10m';
ALTER SYSTEM SET internal_sql_execute_timeout='30s';-- 恢复默认值
同时,SQL 执行时间也受事务超时控制,必要时还需要调整 ob_trx_timeout 系统变量的值。
适用版本
OceanBase 数据库 V3.x、V4.x 版本。