DDL流程概括

    OceanBase支持传统数据库的DDL语句,DDL类型的SQL语句不会被优化器处理,而是作为command发送到RootServer,由RootServer进行处理,比如典型的建表语句,在OceanBase上的执行流程如下图所示。

    DDL语句处理与Schema同步 - 图1

    DDL产生的schema信息使用内部表记录,这样的好处有:

    • 直接利用SQL的事务及持久化能力

    • schema变更信息可以通过sql语句直接获取,避免了多集群之间的同步

    • 天然地享受OceanBase自身的多副本容灾特性

    所有的DDL在线变更都记录在内部表中,内部表本身也支持DDL变更,这样使得集群升级变得非常方便。

    DDL语句处理与Schema同步 - 图2

    __all_table_history记录用户表每个版本的schema信息:

    1. OceanBase (root@oceanbase)> desc __all_table_history ;
    2. +--------------------------------------+---------------------+------+-----+----------------------+-----------------------------+
    3. | Field | Type | Null | Key | Default | Extra |
    4. +--------------------------------------+---------------------+------+-----+----------------------+-----------------------------+
    5. | gmt_create | timestamp(6) | YES | | CURRENT_TIMESTAMP(6) | |
    6. | gmt_modified | timestamp(6) | YES | | CURRENT_TIMESTAMP(6) | ON UPDATE CURRENT_TIMESTAMP |
    7. | tenant_id | bigint(20) | NO | PRI | NULL | |
    8. | table_id | bigint(20) | NO | PRI | NULL | |
    9. | schema_version | bigint(20) | NO | PRI | NULL | |
    10. | is_deleted | bigint(20) | NO | | NULL | |
    11. | table_name | varchar(128) | YES | | | |
    12. | database_id | bigint(20) | YES | | NULL | |
    13. | table_type | bigint(20) | YES | | NULL | |
    14. | load_type | bigint(20) | YES | | NULL | |
    15. | def_type | bigint(20) | YES | | NULL | |
    16. | rowkey_column_num | bigint(20) | YES | | NULL | |
    17. | index_column_num | bigint(20) | YES | | NULL | |

    __all_core_table记录内部表的schema信息(KV方式存储)。

    1. OceanBase (root@oceanbase)> desc __all_core_table;
    2. +--------------+----------------+------+-----+----------------------+-----------------------------+
    3. | Field | Type | Null | Key | Default | Extra |
    4. +--------------+----------------+------+-----+----------------------+-----------------------------+
    5. | gmt_create | timestamp(6) | YES | | CURRENT_TIMESTAMP(6) | |
    6. | gmt_modified | timestamp(6) | YES | | CURRENT_TIMESTAMP(6) | ON UPDATE CURRENT_TIMESTAMP |
    7. | table_name | varchar(128) | NO | PRI | NULL | |
    8. | row_id | bigint(20) | NO | PRI | NULL | |
    9. | column_name | varchar(128) | NO | PRI | NULL | |
    10. | column_value | varchar(65536) | YES | | NULL | |
    11. +--------------+----------------+------+-----+----------------------+-----------------------------+

    由于支持多节点自动同步以及多版本,OceanBase内部很多的功能模块都设计成了类DDL语句,所以OceanBase的DDL已经是个庞大的模块系统,包括:

    • tenant

    • user

    • database

    • table

    • table_group/partition_group

    • outline

    • planbase_line

    • package

    • privilege

    • synonym

    schema多版本

    对于单机数据库,schema对多版本的需求并不强,只需保证schema变更的时序性。典型的实现中,通过DML与DDL之间的锁来保持时序性。OceanBase中schema支持多版本的需求体现在如下几个方面:

    • DML与DDL互相不阻塞,提高性能

    • 分布式事务。对于分布式执行计划,多个机器上的schema必须保持一致

    • 版本冻结。OceanBase是存储架构基于LSM-Tree,当内存增量数据达到阈值时需要冻结。发起冻结的leader需要将schema的版本同步给follower, follower才能冻结

    • 分区合并。 OceanBase总是先冻结后合并,合并是延后调度的,当执行合并时,需要取相应冻结点的schema

    • 异构同步。OceanBase数据同步到其它数据库中时,是基于事务日志回放来完成的。解析历史事务日志时,需要获取相对应的schema信息为了支持多版本,需要将表的变更信息全部持久化到内部表中,包括删除动作,多版本schema内存管理如下图所示。

    DDL语句处理与Schema同步 - 图3

    集群同步

    所有DDL都会被转发给RS来统一调度。将schema从内部表load到内存的过程称为刷schema。RootServer执行内部表的更新后,需要将schema刷到最新,以保持最新的schema信息。然后将新的版本号通知所有在线的ObServer,每个ObServer都收到通知后,此DDL即可正常返回。除了正常通知外,心跳包也会将最新版本号发给每个ObServer。当ObServer收到DDL变更后的版本号后,构造刷schema任务以刷新此ObServer的schema。

    全量刷新与增量刷新

    schema的更新分为全量和增量两种,具体的更新流程如下图所示。

    DDL语句处理与Schema同步 - 图4