在MySQL数据库管理体系中,数据定义语言(DDL)和数据操作语言(DML)构成了数据库交互的基础。
DDL用于定义数据库对象,如数据库、表、列、索引等,相关命令包括CREATE、ALTER、DROP;DML则负责处理数据库中的数据,如插入、更新、删除,对应命令为INSERT、UPDATE、DELETE。
值得注意的是,DML操作可手动控制事务的开启、提交与回滚,而DDL操作是隐性提交,无法回滚,因此执行时需格外谨慎,且通常建议在业务低峰期进行。
一、MySQL DDL的演进——Online DDL的诞生
早期MySQL版本中,特别是在5.6之前,DDL操作尤其是ALTER语句,会严重阻塞表的读写操作。传统的DDL执行过程,需要新建临时表,对原表加写锁,拷贝数据,最后删除原表并对新表重命名。这一过程不仅耗时,还会占用大量额外存储空间,导致在数据拷贝期间,表的DML和DDL操作全部阻塞,极大影响数据库服务的可用性。
为解决这一问题,MySQL引入了Online DDL技术。它支持更多类型的ALTER TABLE操作,在执行DDL期间允许DML操作,避免了对数据库服务的中断。不过,并非所有DDL操作都支持Online操作。
二、Online DDL的运行机制
1. 执行流程
Online DDL通过建立临时文件,扫描原表主键数据页,生成B+树存储到临时文件。在这一过程中,所有对原表的操作会记录在日志文件(row log)中。临时文件生成后,日志文件中的操作会应用到临时文件,使其在逻辑数据上与原表相同,最后用临时文件替换原表数据文件。
2. 语法特性
使用ALTER TABLE语句时,可以指定ALGORITHM和LOCK参数。例如,“ALTER TABLE tab ADD COLUMN c varchar(50), ALGORITHM=INPLACE, LOCK=NONE;”。ALTER语句启动时会获取MDL写锁,在真正拷贝数据前退化为读锁,既保证了DDL执行期间DML操作的并发,又防止其他线程同时对表进行DDL操作。
3. 算法类型
- Copy算法:MySQL 5.5及以下版本的默认算法。执行时会创建临时表,对原表加写锁,拷贝数据,完成后删除原表并重命名临时表。此过程锁表时间长,不支持并发DML写操作,适用于会导致行记录格式变化的操作,如删除主键、修改列类型等。
- Inplace算法:MySQL 5.6开始引入并默认使用。该算法直接在原表上进行更改,无需生成临时表和数据拷贝。根据是否需要重建表,又分为rebuild和no - rebuild两类。前者适用于添加索引、添加/删除列等操作,通过缓存DDL期间的DML并在完成后应用到表上实现Online;后者适用于删除索引、修改列名等只需修改表元数据的操作。
- Instant算法:MySQL 8.0.12开始引入并默认使用。目前仅支持增加列等少量DDL类型操作,其他操作仍默认使用inplace算法。
4. 锁策略
MySQL默认在执行DDL期间使用尽可能少的锁,也可通过LOCK子句控制锁级别。
- DEFAULT:使用当前操作支持的粒度最小的锁策略。
- NONE:不获取任何表锁,允许所有DML操作。
- SHARED:对表添加共享锁(读锁),仅允许只读DML操作。
- EXCLUSIVE:对表添加排他锁(写锁),禁止任何DML操作。
5. 执行阶段
Online DDL主要包括prepare、ddl执行和commit三个阶段:
- Prepare阶段:初始化并计算DDL过程中的并发量,获取shared metadata lock保护表结构定义,创建临时frm文件,根据操作类型确定执行方式,更新数据字典内存对象,分配row_log记录增量(仅rebuild类型需要),生成临时ibd文件(仅rebuild类型需要),最后提交事务并释放锁。
- DDL执行阶段:降低EXCLUSIVE - MDL锁级别,允许读写(copy算法不可写),扫描原表聚集索引记录,构造新索引项并插入,记录增量(仅rebuild类型需要),重放row_log操作到新索引上。
- Commit阶段:将shared metadata lock升级为exclusive metadata lock,禁止DML,重做row_log最后部分增量,更新InnoDB数据字典表,提交事务,修改统计信息,重命名临时文件,完成变更。
三、Online DDL语法规范
Online DDL为加列、加索引等操作提供了更为灵活和高效的语法支持。在加列操作时,基本语法为“alter table 表名 add column 列名 数据类型,ALGORITHM 算法”。例如,“alter table t3 add column name1 varchar(16),ALGORITHM INPLACE/COPY/DEFAULT”。实际应用中,也可省略算法指定,系统会根据具体情况自动选择最优算法,如“alter table t3 add column name1 varchar(16)”。加索引操作的语法与之类似,“alter table 表名 add index 索引名(列名),ALGORITHM INPLACE”,同样支持省略算法指定。需注意,COPY算法本质上属于离线操作,默认情况下,系统会智能选择合适的算法。
四、Online DDL的COPY模式
1. COPY算法操作实例
以“alter table sbtest1 add column c varchar(122), ALGORITHM=COPY”操作为例,其执行过程可划分为准备、执行和提交三个阶段。
2. 三阶段执行流程
- 准备阶段:首先对元数据添加共享锁(MDL-S),读取原表结构,此过程短暂且不阻塞DML,但禁止DDL操作。随后,共享锁升级为排他锁(MDL-X),此时DDL和DML操作均被阻塞。接着,server层执行类似“create table”的语句,创建与原表结构一致的临时表,引擎层也会生成相应的frm和ibd文件。
- 执行阶段:对新创建的临时表进行表结构修改。完成修改后,server层将原表数据拷贝到临时表中,这一过程会阻塞DML操作,阻塞时长取决于数据拷贝速度。数据拷贝完成后,server层重命名临时表及文件,使其替代原表,并删除原表所有数据。
- 提交阶段:执行commit操作,释放所有锁。
3. COPY算法的特点
从操作开始到结束,MDL-X锁一直存在,这会阻塞所有DDL和修改类DML操作,不过大多数情况下SELECT操作不受影响。由于整个DDL执行阶段都会阻塞业务,因此COPY算法不属于严格意义上的Online DDL。
五、Online DDL的INPLACE模式
1. 执行原理概述
INPLACE模式同样遵循准备、执行和提交三阶段模型。该模式于MySQL 5.6版本引入,将执行流程下推至引擎层,减少了对业务的影响。
2. 三阶段执行流程
- 准备阶段:在进入准备阶段前,对元数据持有可升级的S锁(MDL-S锁),此阶段禁止DML和部分DDL操作,如drop操作。进入准备阶段后,MDL-S锁升级为X锁,系统会判断操作是否需要重建表。若需要重建表,会申请row log空间,用于记录Online DDL执行阶段对原表数据的DML操作,其空间大小由innodb_sort_buffer_size决定。若需重建表,引擎层会生成原表的转储文件(如ibd、frm文件);若无需重建表,引擎层仅生成frm文件,如加索引操作。
- 执行阶段:执行阶段将MDL-X锁降级为S锁,此阶段不阻塞DML操作,因此被称为Online阶段。在该阶段,引擎层会将原表存储的数据读取到准备阶段创建的ibd文件中,通过分析数据页和内部结构,逐行取出原表数据记录进行处理,并将DDL表结构修改应用到新的ibd文件中。
- 提交阶段:引擎层将row log中的操作应用到新的ibd文件中,直至最后一个操作,系统会自动截断,避免DML操作持续影响。此时,MDL-S锁再次升级为MDL-X锁,拒绝所有DML操作,将row log中剩余的数据应用完毕。随后删除原表,用新表替换原表,清理老文件,完成提交操作。
六、Online DDL常见问题剖析
1. Online DDL是否锁表?
从用户角度看,Online DDL在执行DDL期间不阻塞DML操作。但从管理员角度分析,准备阶段持有X锁,会阻塞DML;执行阶段降级为S锁,不阻塞DML;提交阶段升级为X锁,再次阻塞DML。
2. 支持INPLACE算法的DDL一定是Online的吗?
不一定。COPY和INPLACE算法的第一、三阶段对用户而言并非Online,只有第二阶段对用户来说是Online的。COPY算法执行的DDL肯定不是Online的,而INPLACE算法执行的DDL也不一定是Online的。
3. Online DDL是否需要额外磁盘空间?
对于引擎层需要创建ibd转储文件的操作,需要额外的存储空间。操作时长会受到数据量影响,但不会阻塞业务。
4. COPY方式和INPLACE方式有何区别?
COPY方式在server层进行操作,而INPLACE方式在engine层执行,这使得INPLACE方式能够更好地实现对业务影响的最小化。
5. 如何判断是rebuild table还是no rebuild table?
一方面,可以观察DDL执行时间,若执行阶段耗时较长,很可能是rebuild table方式。另一方面,可观察数据目录下是否生成#sql_xxx.ibd/frm文件,特别是ibd文件且其大小持续增大,也表明是rebuild table操作。
6. 如何判断是否为Online DDL?
执行DDL操作后,若返回“Query OK, 0 rows affected”,则大概率是Online DDL;若返回非0行影响,则可能是Offline DDL。
七、总结
加索引和加列等DDL操作会受到原表数据的影响。INPLACE模式之所以被称为原地操作,是因为其不涉及server层的表重建操作,而是将操作下推到引擎层执行。在INPLACE模式中,虽然无需通过server层的create语句重建表,但引擎层仍需生成ibd转储文件,因此这类操作仍需额外的存储空间。尽管Prepare阶段和Commit阶段会短暂加锁,但执行DDL阶段的Online特性,使得对原有业务的DML操作基本不会造成阻塞,不过可能会对系统负载和IO产生一定影响。如需了解更多Online DDL相关内容,可访问官方文档https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-operations.html 。