OceanBase 支持多版本的表模式,主要的原因是避免 DDL 操作和 DML 操作相互阻塞,对分布式系统来说,这一点尤为重要。每一次 DDL 操作都会引起数据库中对象的变化,为标识这些变化,每一个数据库对象都有一个版本号,在 OceanBase 中用变更(创建或者更改)时的时间戳来表示版本号。
以用户表 T1 为例,创建的时候有一个版本号 V1,后续的每一次变更都会新生成一个版本号 Vn。对表T1来说,就唯一标识了表 T1 的一个特定的版本。在每一个给定的时间点 Ti,该时刻数据库中所有对象的最新状态的集合就构成了此时数据库元信息的一个快照 Si。快照 Si 是语句执行的基础,每一条语句的执行都是基于语句开始时获取到的Si。
多版本的 Schema 对 OceanBase 至关重要。对于分布式执行计划,需要在多个 OBserver 上执行,执行时必须与计划生成时的表模式保持一致。版本冻结也要保证每个参与的 OBServer 具有相同版本的表模式。此过程中,发起冻结的 leader 需要将 schema 的版本同步给 followers,followers 拿到此版本的 schema 才能执行冻结。冻结之后的数据合并过程是延后调度,当合并执行时,需要取老版本的 schema 信息。从 OceanBase 中同步数据到其他数据库系统中,采用的方式是解析 OceanBase 的数据库日志,结合表模式信息形成一条 SQL 语句,然后通过在目标数据库中执行 SQL 语句来实现的。由于同步的日志可能是很久以前的,就需要获取历史版本的表模式信息。
OceanBase 将对表的每次模式变更相关的信息记录下来,持久化到内部表中,通过保留完整的历史信息,每个模式变更的操作都做到可以跟踪。为了控制存储占用的空间及提升历史信息的查询性能,会定期清理变更时间超出阈值的历史信息。
OceanBase 在内存中保存多个版本的模式信息,除最新版本外,还有若干个历史版本。如果某次操作需要的模式信息版本在内存中不存在,则通过在最新版本上根据历史变更信息进行回滚的方式构造。