内容概述:
- Online DDL的算法
- Online DDL的分类
- Online DDL的实现原理
- Mysql中如何查看DDL操作的进度
概念描述
Online DDL算法
在MYSQL 5.6版本之前,所有DDL操作都会阻塞DML,仅允许SELECT。当时DDL支持的算法有两种:COPY和INPLACE。
(1)COPY算法的实现原理:
- 新建临时表。
- 对原表加锁,这个时候会阻塞DML,只允许SELECT操作。
- 将原表的数据逐行拷贝到临时表里面。
- 升级字典锁,禁止读写,执行RENAME操作。
INPLACE算法是5.1版本引入的,仅适用于索引的创建和删除。在INPLACE的方式下,索引可以直接在原表上创建,并不会新增临时表,因此效率较高,但其与COPY算法一样都会阻塞DML。
(2)INPLACE算法的实现原理:
- 新建索引的数据字典。
- 对原表加锁,这个时候会阻塞DML,只允许SELECT操作。
- 读取聚簇索引,构造新的索引项,排序并插入新索引。
- 等待当前表的所有只读事务提交。
- 创建索引结束。
以上为旧版本内容回顾,下面进入正题:Online DDL是MYSQL 5.6.7版本开始引入的,这里的Online,指的是在线上环境的DDL执行过程中,不会阻塞DML的操作。但要注意并不是所有的DDL都不会阻塞DML。
首先说说ALTER TABLE操作中关于DDL的两个子句:ALGORITHM和LOCK
例:alter table t1 ............, ALGORITHM=......, LOCK=...... ;
1,ALGORITHM子句指定了DDL操作使用的算法,包括上面提到的COPY,INPLACE,还有DEFAULT(缺省值),和8.0.12版本引入的INSTANT。
- INPLACE算法除了上面提到的可以支持在原表上进行操作外,还包括了rebuild方式和no-rebuild方式两类。其中rebuild方式会重建表,no-rebuild方式只会修改表的元数据信息,显然,no-rebuild方式的效率会更高。
- DEFAULT为不指定ALGORITHM时的缺省值,将由MYSQL自行决定DDL执行时使用的算法。优先级INSTANT>INPLACE>COPY。
- INSTANT:MYSQL8.0.12版本引入的新算法,只会修改表的元数据信息,支持表的秒级加列特性。
2,LOCK子句指定了DDL操作的锁级别,有如下取值:
- NONE:允许SELECT和DML操作。
- SHARED:允许SELECT,阻塞DML。
- EXCLUSIVE:阻塞SELECT和DML。
- DEFAULT:缺省值,由MYSQL自行决定LOCK的级别,优先级NONE>SHARED>EXCLUSIVE。
注意:当ALGORITHM子句设置为COPY时,LOCK只能设置为SHARED或EXCLUSIVE,如果不指定LOCK,则默认为SHARED。
从上面两个子句的选项来看,只有DDL算法选择ALGORITHM = INSTANT 或 INPLACE(no-rebuild),并且LOCK = NONE时,才算得上真正意义上的Online DDL。
然后,说说Online DDL的分类:根据ALGORITHM选项和LOCK级别,可以分为3类:
一,只修改表的元数据信息(INSTANT或INPLACE的no-rebuild方式),也是3类Online DDL中性能最好的一类,对业务影响最小。
属于此类的DDL操作如下:
- 删除二级索引
- 修改索引名称(MYSQL 5.7开始支持,5.6版本中如果要修改索引名称,只能重建索引)
- 修改字段名称(注意只有字段名称,不包含字段属性)
- 增加VARCHAR的长度(MYSQL 5.7开始支持,5.6版本中如果要增加VARCHAR长度,只能使用COPY算法)注意:如果要减小VARCHAR长度,无论哪个版本中,都只能使用COPY算法,另外如果增加的字符串长度超过了当前所表示的字节数,也会使用COPY算法。这取决于当前MYSQL的字符集类型。举例说明:比如varchar(50),表示字符串范围在一个字节内(0-255),如果此时MYSQL的字符集时utf8(一个字符最多占3字节),那么,如果想使用INSTANT或INPLACE no-rebuild算法的话,varchar(50)字段最多可以增加到varchar(85),因为255/3=85,如果增加到varchar(86),那么该字符串就从原来的一个字节表示为两个字节,一旦表示字符串的字节数发生了变化,就只能使用COPY算法。
- 修改自增主键的值:alter table t1 AUTO_INCREMENT=next_value; 这里修改的其实是内存值。
- 修改表的统计信息相关选项,如:alter table t1 STATS_PERSISTENT=1, STATS_AUTO_RECALC=1, STATS_SAMPLE_PAGES=20;
- 重命名表(RENAME table)
- 添加外键约束:这里又区分两种场景:如果foreign_key_eechecks参数为on,会使用COPY算法,只有foreign_key_checks为off时,才会只更新表的元数据信息。
- 删除外键约束:不论foreign_key_checks参数是on还是off,都会只更新表的元数据信息。
总结:此类DDL操作,在MYSQL 8.0.12引入INSTANT算法之前,使用的时INPLACE算法的no-rebuild方式,引入INSTANT算法后,很多此类操作使用的是INSTANT,但本质不变。
此类只修改表的元数据信息的Online DDL操作有如下特点:
- 不会阻塞DML。
- 耗时极短,如果表上没有正在执行的SELECT或事物,这类操作几乎会瞬间完成。
- 只会更新表结构文件(.frm),不会更新.ibd文件。
二,INPLACE算法的rebuild方式,此类DDL需要DBA根据具体情况评估执行影响,尤其表很大时,不建议业务高峰时段执行。
属于此类的DDL操作如下:
- 创建索引:其实创建索引应该属于INPLACE算法的no-rebuild方式,因为在执行过程中也不会创建临时的.ibd文件。放在这里是因为考虑到它的执行时间受表本身的大小影响。
- 添加主键。
- 删除主键的同时添加另一个主键:如:alter table t1 drop PRIMARY KEY, ADD PRIMARY KEY (id_1);,如果仅仅是删除主键,则只能选择COPY算法。
- 新增字段:从MYSQL 8.0.12开始,新增字段可以使用INSTANT算法实现秒级加列。但要注意如果添加的字段为自增列时,仍然会阻塞DML。
- 删除字段:从MYSQL 8.0.29开始,删除字段可以使用INSTANT算法。但要注意,如果删除的字段只有主键,则只能使用COPY算法。
- 调整字段的顺序。
- 修改表的属性(ROW_FORMAT 和 KEY_BLOCK_SIZE)
- 修改字段的NULL属性:分两种情况:如果是添加NULL属性,如:alter table t1 MODIFY col_01 varchar(60) NULL; 默认使用INPLACE的rebuild法。但如果是添加NOT NULL属性,如:alter table t1 MODIFY col_01 varchar(60) NOT NULL; ,那么sql_mode必须为STRICT_ALL_TABLES或者STRICT_TRANS_TABLES,否则仍会使用COPY算法。
- OPTIMIZE TABLE操作:对于Innodb表来说,optimize table实际上对应的就是alter table ... force命令,该命令会重建表,回收空闲空间,并更新表的统计信息。在表碎片比较多的情况下,推荐使用该命令。但要注意如果表中存在FULLTEXT索引的话,该操作会使用COPY算法。
- 同理,ALTER TALBE ... FORCE 和 ALTER TABLE ... ENGINE=INNODB 作用同 OPTIMIZE TABLE类似,也会使用到INPLACE的rebuild法。
使用INPLACE rebuild算法的Online DDL操作有如下特点:
- 不会阻塞DML。
- 执行时间与表的大小成正比,表越大,执行时间越长。
- 在执行过程中,会拷贝原表的数据。具体来说,会在原表当前的目录中创建临时的.frm文件和.ibd文件,所以这个过程对数据库性能会存在影响,需要提前做出评估。
三,COPY算法,与INPLACE算法的rebuild类型一样,都会在原表当前目录下创建临时的.frm和.ibd文件,但不同的是INPLACE的rebuild算法不会阻塞DML操作,但COYPY算法会阻塞。
属于此类的DDL操作如下:
- 修改字段定义:常见有两种:调整字段的类型,调整字段的长度(注意与INPLACE no-rebuild算法中的增加varchar长度做区分,不要混淆概念)。
- 删除主键
- 调整表的字符集:alter table t1 convert to character set charset_name [COLLATE collation_name]
(未完待续......)




