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算法,如新增/删除列,新增/删除索引。