共计 1669 个字符,预计需要花费 5 分钟才能阅读完成。
Online Schema Change – 在线更新元数据性能,以下简称 OSC。
传统的关系型数据库在执行 Schema 变更时,为了保证数据一致性须要锁表,锁表期间任何读写操作都会受到阻塞,直到 Schema 变更完结,开释表锁。
这样做法使解决流程简单化,但同时弊病也很显著,那就是其余的 DML 操作都会受到阻塞,影响失常业务。
开务数据库的 OSC 引进 2 个中间状态,通过管制过渡状态来保证数据一致性且不须要锁表,因此不影响失常业务。为不便后续了解,这里先列举常见的 4 种 OSC 状态:
1、Absent 此状态下 Schema 不存在,定义的对象不可用。Schema 对所有操作不可见,不可读写。
2、DescriptorMutation_DELETE_ONLY 指变更的这部分 Schema 只对删除操作可见。
3、DescriptorMutation_DELETE_AND_WRITE_ONLY 指变更的这部分 Schema 只对写操作可见,包含 Insert, Delete, Update。
4、PublicSchema 已实现变更,定义的对象齐全可用。Schema 对所有操作可见,定义的对象可读可写。
接下来通过“Create Index” 实例,介绍开务数据库在理论业务中如何保持数据一致性且不影响失常业务流程 >>
第 1 步:由 Absent 状态演进到 DELETE_ONLY 状态,Version+1,Mutation 对 Delete 操作可见;
第 2 步:通过 waitToUpdateLeases 函数期待集群的其余节点将表元数据更新到 Version2,这期间 Version2 和 Version1 共存,此时在 Node2 插入业务数据,因为 DELETE_ONLY 状态下 Insert 对 Mutation 不可见,不会减少索引数据,所以不会呈现数据不统一状况;
第 3 步:由 DELETE_ONLY 状态演进到 DELETE_AND_WRITE_ONLY 状态,Version+1,Mutation 对 Insert 和 Delete 可见;
第 4 步:通过 waitToUpdateLeases 函数期待集群的其余节点将表元数据更新到 Version3,这期间 Version3 和 Version2 共存,此时在 Node2 插入业务数据,因为 DELETE_AND_WRITE_ONLY 状态 Mutation 对 Insert 可见,所以会减少索引数据,Node1 还是 DELETE_ONLY 状态,Delete 业务数据能把对应的索引数据也删除,所以不会呈现数据不统一状况;
第 5 步:可选,须要做数据回填的 DDL 语句(减少索引、删除列、减少带默认值的列);
第 6 步:由 DELETE_AND_WRITE_ONLY 状态演进到 Public 状态,Version+1,Mutation 对 Insert、Delete 和 Read 可见;
第 7 步:通过 waitToUpdateLeases 函数期待集群的其余节点将表元数据更新到 Version4,这期间 Version4 和 Version3 共存,此时在 Node2 插入业务数据,因为 Public 状态 Mutation 对 Insert 可见,所以会减少索引数据。Node1 还是 DELETE_AND_WRITE_ONLY 状态,Delete 业务数据能把对应的索引数据也删除。相同 Node1 插入业务数据也会减少索引数据,Node2 删除业务数据也能删掉索引数据,所以不会呈现数据不统一状况。
至此,实现了创立索引的变更,因为每 2 个版本是兼容的,所以实现变更之后能保证数据的一致性。最初为大家梳理一下整体的脉络流程:
1、执行算子,往表描述符增加变更操作 Mutation;
2、执行算子,生成 Job 信息,往 System.jobs 零碎表插入信息;
3、将 DDL(Data Definition Language)事务状态转为 Commit;
4、通过 Channel 告诉后盾 Work 解决 Job;05 后盾 Work 遍历 System.jobs,找到 Lease 属于本节点且状态为 Running 的 Job,并为每个 Job 起一个 Goroutine 进行解决。