Online DDL
核心目标
在传统模式下,变更表结构(如加字段、加索引、该字段类型)会对表上排他锁。对于数据量大的表,变更可能持续数小时甚至数天,在此期间,数据库所有增删改查操作会被阻塞,业务无法使用,在要求7x24可用的业务中,这是不可接受的。
在线表结构变更技术能在不影响或极小影响数据库正常提供服务的情况下,完成表定义的修改,是保障数据库平滑演进和业务连续性的关键
工作机制
整体流程
变更表结构整体遵循以下流程:获取 DDL Latch (共享锁) -> 执行变更 -> 释放 DDL Latch
通常情况下,变更操作在开始前会对需要变更的表及其父表和子表添加表级排他锁,并在变更结束后释放锁,在持有表锁期间会阻塞所有 DML。oGRAC对此进行了大量优化。
影子索引
索引创建操作本身是一个资源密集型任务,除了巨大的资源消耗外,还会导致数据库长时间不可用。常规在线重建,后台索引修改和前台DML操作交织,在极端情况下可能增加死锁发生的概率。
oGRAC采用影子索引技术,将索引的“物理创建“和“逻辑启用“两个动作分开,在两者之间引入一个“缓冲区”。在后台安全的创建索引,此过程索引始终是不可见的,由于优化器忽略它,即使创建过程慢一点,也不会导致执行计划突然变化的风险。增删改操作都会在影子索引上操作一遍,当索引创建完成后,通过一个极快的元数据修改操作,将“影子索引”上线。
后台创建索引不需要加表级互斥锁,元数据修改操作耗时在毫秒级,通过影子索引技术,实现了一种完全不阻塞 DML的在线创建索引方法,是Online DDL的一种更高级、更安全的实现模式。
并行DDL
传统表变更时,单个进程执行所有工作,在处理大规模数据时,其缺点变得非常突出。无法充分利用硬件资源执行效率低,阻塞时间长,与现代化运维理念背道而驰。为了解决传统表变更的痛点,oGRAC引入了并行DDL技术,利用多线程来执行单个 DDL 操作,从而显著加速大规模数据定义语言操作的速度。
以并行重建索引为例,oGRAC会初始化工作线程池,池大小默认等于CPU核心数。协调线程根据 PARALLEL 指令指定的并行度,将表或索引的数据块范围动态分配给工作线程,每个工作线程扫描自己负责的数据,由协调线程将所有工作线程的结果合并写入到新的索引段。工作线程运行任务动态调整,过载线程任务分割由空闲线程处理,整个过程充分利用了多核CPU的并行计算能力。
数据字典
系统表是管理数据库中所有对象的元数据表,是数据库存取数据的入口。DC(数据字典缓存),读取系统表,按照一定的结构将各种对象加载内存,以方便数据库对象的查找和管理。DC的存在,透明化系统表的访问并加速访问过程。
Entity是实体,它真正意义上的扫描对象的元数据,表结构不是一成不变的,因此存在多版本Entity,每次打开对象时访问的都是最新版本的Entity,所以执行DDL操作后会设置失效。当执行时会检查chg_scn和valid标记,如果失效会重新打开。
应用场景
| 操作 | 具体操作 | 允许并发DML | 允许并发DQL | 备注 | |
|---|---|---|---|---|---|
| 二级索引操作 | 添加二级索引 | 是 | 是 | 开始和结束阶段短暂影响DML | |
| 删除二级索引 | 否 | 是 | |||
| 重命名索引 | 否 | 是 | 只修改元数据,短暂影响DML | ||
| 主键操作 | 添加主键 | 否 | 是 | ||
| 删除主键 | 否 | 是 | |||
| 列操作 | 添加列 | 否 | 是 | 如果添加NULL列,短暂影响DML | |
| 删除列 | 否 | 是 | |||
| 重命名列 | 否 | 是 | 只修改元数据,短暂影响DML | ||
| 更改列类型 | 否 | 是 |
最佳实践
在业务低峰期操作
尽管是在表表结构变更,但并发零影响。变更期间可能会构建索引树、读取表数据并写入新数据。这可能会导致额外的CPU/IO消耗,影响数据库性能。