1、背景:没有引入Online DDL之前,业务系统的数据表变更要么直接alter table,要么采用不阻塞业务的PT工具执行变更(变更流程较重)。
Online DDL从MySql 5.6.7以后,已经有很大的改进,能够支撑多种类型的表结构变更,达到变更不中断业务的诉求。
目前华为云mysql rds版本为可支持到5.7.27+,刚好可以很好的引入online ddl(既有能力),优化变更流程。
2、Online DDL语法:
alter table …. , ALGORITHM [=] { INPLACE | COPY | DEFAULT}, LOCK [=] { DEFAULT | NONE | SHARED | EXCLUSIVE }
# 示例
ALTER TABLE table_name algorithm=inplace, add column_name varchar(100) COMMENT '注释';
说明:
ALGORITHM包含inplace和copy两种,优先采用inplace,这样可以减少IO/buffer pool资源占用,降低对RDS性能开销,注意:有些DDL不支持inplace,后续会详细阐述!
注意:采用inplace算法时,判断DDL是否修改行记录格式?是:rebuild表,否:no-rebuild表
LOCK DDL加锁的方式NONE 不添加锁,既允许查询操作,也支持数据库变更操作,该模式下并发最好
SHARED 对整个表格添加(S锁),允许查询操作,但是不支持修改
EXCLUSIVE 对整个表格添加独占锁(X锁),不允许查询和修改
DEFAULT 没有指定LOCK的时候,也是默认(优选方案),最小锁原则:首先优先NONE,不能再SHARE,还不能就EXCLUSIVE。
3、Online DDL支持情况:
本章节重点罗列常用的变更语句进行说明,DDL并发DML?Inplace?Rebuid-Table说明
1add/drop/rename indexYYN不包含全文索引,drop/rename只用修改元数据
2add fulltext indexN*YN*表格中第一个全文索引要rebuild,增加第2...n个全文索引不用rebuild
3set column默认值YYN仅修改元数据
4add/drop/rename columnYNY数据重组,所以它仍然是一项昂贵的操作。当添加列是auto-increment,不允许DML并发;rename时,允许并发DML,需要保持类型相同
5drop and add primary keyYYYalter table o_ddl algorithm=inplace, drop primary key,
add primary key(n_id)
6drop primary keyNNYalter table o_ddl algorithm=copy, drop primary key 只支持copy
7add primary keyY*YY尽管inplace,但是要重组数据--高开销。如果列要转化NOT NULL,则不允许INPLACE
8varchar 长度增加YYN扩容非常快
9varchar 长度减少NNY只能COPY
10change column DateTypeNNY
11add/drop foreign key constraintYYNforeign_key_checks开启时,add只能是copy
12change auto-increment valueYYN修改自增长步长
13add spatial indexNYN空间索引,使用点较少
14optimize tableYY*Y带全文索引不支持inplace
4、MySQL处理Online DDL原理(了解即可):
Online DDL处理有3个阶段:prepare、execute、commit
PREPARE创建新的临时frm文件
持有EXCLUSIVE_MDL锁,禁止读写
根据alter类型,确定执行方式(copy,rebuild,no-rebuild)
更新数据字典的内存对象
若是需要rebuild,分配row_log记录增量数据,并生成临时ibd文件
EXECUTE如果是仅修改元数据:
本阶段无操作
其他:降低EXCLUSIVE-MDL锁,允许读写(copy 不允许写)
记录ddl执行过程中产生的增量row-log(仅rebuild类型需要)
扫描old_table的聚集索引每一条记录record
遍历新表的聚集索引和二级索引,逐一处理
根据record构造对应的索引项
将构造索引项插入sort_buffer块
将sort_buffer块插入新的索引
把row-log中的操作应用到新临时表中,应用到最后一个Block
COMMIT升级到EXECLUSIVE-MDL锁,禁止读写
重做最后一部分的row_log增量
更新innodb的数据字典表
提交事务,写redo日志
修改统计信息
rename 临时的ibd文件、frm文件
DDL完成
注意:row-log是记录 DDL在执行过程中表格发生数据变更的操作,这样就可以保证执行DDL表格的并发性,在EXCUTE阶段可以正常提供写服务,不发生堵塞,最后把row-log应用到新的表格上即可。