inplace DDL是什么
In-place DDL(原地DDL或在线DDL)是一种在数据库中执行数据定义语言(DDL)操作(如 ALTER TABLE)的机制,其核心特点是避免对整张表进行数据的完整复制和重建。它直接在原始表的数据文件上进行结构修改,从而显著减少操作期间的资源消耗和对业务的影响。
这个概念在处理大表的结构变更时尤其重要,是现代关系型数据库(特别是MySQL的InnoDB存储引擎)提升可用性的关键特性之一。
核心思想:原地装修 vs. 拆了重建
为了更好地理解,我们可以用一个比喻:
-
传统DDL(Copying DDL):就像你要给一个房间(数据表)增加一根柱子。传统方法是,你在旁边找块空地,按照新的图纸(新表结构)盖一个一模一样的新房间,然后把旧房间里的所有家具(数据)一件一件搬到新房间,最后拆掉旧房间,让新房间顶替它的位置。这个过程耗时耗力,而且在“搬家”期间,这个房间基本无法正常使用(表被长时间锁定)。
-
In-place DDL:则像是直接在原来的房间里施工。工人(数据库引擎)带着工具和材料进来,在不把所有家具都搬出去的情况下,直接在房间内部把柱子建好。这个过程中,房间可能短时间会有一些干扰(短暂的锁),但大部分时间里,人们还是可以进出和使用房间里的家具的(表在大部分时间内可读写)。
传统DDL(Copying方式)的工作流程
- 创建一个符合新表结构的临时表。
- 将原始表锁定,防止数据写入。
- 将原始表中的数据逐行复制到临时表中。
- 在临时表上创建新的索引。
- 复制完成后,将原始表删除,并将临时表重命名为原始表的名称。
- 释放锁。
这个过程的缺点非常明显: * 长时间锁定:在数据复制期间,表通常是只读甚至完全锁定的,对线上业务是灾难性的。 * 双倍空间:需要临时的磁盘空间来存放新表,如果原表是1TB,你就需要额外的1TB空间。 * 高I/O消耗:大量的数据读取和写入会给服务器带来巨大的I/O压力。
In-place DDL的优势
In-place DDL通过避免全表复制,带来了革命性的改进:
- 更高的可用性:操作期间对表的锁定时间极大地缩短,甚至可以实现完全不锁表(允许并发的读写操作)。这被称为“Online DDL”。
- 更少的磁盘空间:不需要额外的空间来创建临时表。
- 更低的I/O负载:只修改与表结构相关的元数据和少量数据页,避免了海量数据的迁移。
在MySQL中的实践
MySQL的InnoDB存储引擎是In-place DDL的典型实践者。从MySQL 5.6版本开始,Online DDL功能得到了极大的增强。在执行ALTER TABLE语句时,可以通过ALGORITHM和LOCK子句来控制DDL的执行方式。
ALTER TABLE table_name [alter_specification], ALGORITHM=INPLACE, LOCK=NONE;
-
ALGORITHM子句:INPLACE:告诉MySQL尽可能使用原地算法。如果该操作不支持INPLACE,则会报错。COPY:强制使用传统的拷贝算法。INSTANT:MySQL 8.0引入的更快的算法,只修改元数据,不涉及数据文件,速度极快(例如,添加列)。DEFAULT:由MySQL自行决定使用最佳算法。
-
LOCK子句:NONE:最理想的状态,允许并发的读和写(DML)。SHARED:允许并发读,但禁止并发写。EXCLUSIVE:完全锁定表,禁止任何读写。DEFAULT:MySQL在保证数据一致性的前提下,选择侵入性最小的锁级别。
并不是所有操作都支持In-place
需要注意的是,并非所有的DDL操作都能以In-place方式完成。这取决于操作的类型和数据库的版本。
通常支持In-place的操作:
- 添加、删除或重命名索引。
- 添加、删除或重命名列(在现代版本中,添加列几乎是瞬间完成的)。
- 修改列的默认值。
- 修改
ENUM或SET列的定义。
通常需要Copying(重建表)的操作:
- 修改列的数据类型(例如
INT改为BIGINT)。 - 修改表的字符集。
- 修改主键。
- 改变表的
ROW_FORMAT。
| 特性 | In-place DDL (原地/在线) | Copying DDL (拷贝/离线) |
|---|---|---|
| 核心机制 | 直接修改原表数据文件,不复制数据 | 创建新表,复制所有数据,然后替换 |
| 可用性 | 高,锁时间极短,甚至无锁 | 低,长时间锁定表 |
| 磁盘空间 | 无需额外空间 | 需要约等于原表大小的额外空间 |
| I/O负载 | 低,仅修改元数据和必要数据 | 高,全表数据的读写 |
| 适用场景 | 对可用性要求高的生产环境,尤其是大表 | 旧版本数据库,或某些不支持In-place的复杂操作 |