InnoDB引擎支持的DDL算法有:

1、COPY,在MySQL5.5及以下为默认算法。

2、INPLACE,在MySQL5.6、5.7为默认算法。INPLACE是原地的意思。在ddl的过程中仍可以读写。

3、INSTANT,在MySQL8.0及以上为默认算法。INSTANT是即时的意思。

使用algorithm关键字来指定ddl算法,如下:

alter table person add column create_time timestamp not null default current_timestamp, algorithm=inplace, lock=none;

假如我们的mysql是5.7.x版本,那么给大表加字段,非常慢,删除字段也很慢,且会占用跟表大小差不多的额外空间,如果有主从同步的话,会造成主从同步延时。

可以开启ddl监控,修改my.conf文件,新增一行performance-schema-instrument = stage/innodb/alter%=ON,之后重启mysql。在执行ddl后,可以通过查看performance_schema库的events_stages_current表来查看ddl的执行进度。

inplace算法又分为inplace-rebuild和inplace-no-rebuild,inplace-rebuild会非常慢,且会占用跟表大小差不多的额外空间,如果有主从同步的话,会造成主从同步延时。

什么情况下不会rebuild table?

1、表重命名、列重命名

2、设置/删除列的default值

3、修改表的auto_increment值

4、重命名索引、删除索引

5、增加varchar列的size

其他情况下都会rebuild table,如新增/删除列、新增索引、修改列类型、缩减varchar列的size等。

有一些第三方工具也可以实现ddl操作,常用的有percona的pt-osc(全称是pt-online-schema-change)和github的gh-ost(全程是gh-online-schema-change-tool)。这两个工具的基本逻辑是根据要操作的表的表结构新建一个表,执行ddl后,copy原表数据到新表,然后把老表重命名,再把新表重命名为老表。若在拷贝过程中,有insert、update、delete语句进来,则需要同步至新表。

 

pt-osc使用trigger,给原表建3个trigger,分别对应insert、update、delete,原表收到这些dml语句后,会同时操作新表。一般来说不推荐使用trigger,所以不推荐使用pt-osc。

gh-ost不使用trigger,而是使用binlog,同步insert、update、delete这些dml语句到新表。

gh-ost用法如下:

gh-ost --host="127.0.0.1" --port=3316 --user="root" --password="123456" --database="test" --table="person" --alter="add column create_time timestamp not null default current_timestamp" -aliyun-rds --allow-on-master --verbose --execute

mysql默认不启用binlog,如果要启用的话,需要修改/etc/my.cnf文件,新增以下两行:

log-bin=/var/lib/mysql/mysql-bin
server-id=1
log_slave_updates=1

如果数据库架构是主从架构,那么应该怎么操作呢?

 

假如我们的mysql是8.0.x版本,那么给大表加字段,非常快,零点几秒就完成了。

什么情况下不支持instant算法?

1、不支持开启压缩的表

2、不支持包含全文索引的表

3、不支持临时表

其他情况下都会使用instant算法,如新增/删除列,新增/删除索引。