MySQL在线修改表结构的影响(MySQL Online DDL)

MySQL Online DDL的改进与应用

MySQL Online DDL

MySQL 不止有增删改数据操作(DML),还有改表结构的操作(DDL),当新增加字段等修改表结构时,就需要进行 DDL 操作。

一般来说,在创建数据表时就应该充分考虑到以后的需求变动,合理设置字段和索引,最好不要修改已有数据表的结构和索引。如果不得不修改已有的数据表的结构(比如增加字段),会给在线业务带来很大的影响。即使需要修改,最好是先再测试库上修改,然后再修改线上的数据库。

本文以Mysql InnoDB为例讲解ddl方法的演变。

使用InnoDB引擎时,在data目录下会看到2类文件:.frm、.ibd

  • .frm–表结构的文件。
  • .ibd–表数据文件

早期DDL

copy table方式

MySQL 5.5之前只有copy table方式。修改表结构使用copy table方式,即拷贝临时表。

此时修改表结构使用表级锁,MySQL 自动完成转存数据,交换表名和删除旧表等操作,时间消耗最多的是在往临时表(Server 层)插入数据的过程。

  • 新建跟原表相同的临时表,并在该临时表上执行DDL语句
  • 锁原表,只允许查询,不允许DML。
  • 从原表逐行拷贝数据到临时表中。
  • 拷贝结束后,原表禁止读操作,也就是原表此时不提供读写服务
  • 删除旧表,rename临时表,完成DDL过程

整个ddl过程中该表只能读不能写(即不能DML),ddl期间不能响应写请求,无法响应业务需求。

inplace 方式

MySQL5.5提出了inplace方式。新建和删除索引可以使用inplace 方式。

  • 新建frm临时文件
  • 锁原表,只允许查询,不允许DML。
  • 按照聚集索引的顺序,查询数据,找到需要的索引列数据,排序后插入到新的索引页中
  • 原表禁止读操作,也就是原表此时不提供读写服务
  • 进行rename操作,替换frm文件,完成DDL过程

在没有inplace方式之前,修改索引只能通过copy table的方式进行,开销很大。提出了inplace方式之后,修改索引就不需要拷贝整个数据表了,只需要新建索引文件,加快了DDL执行速度,减少了数据表不可写的时间。缺点是inplace方式只支持修改索引,修改表结构的DDL操作还是需要使用copy table方式。

Online DDL

MySQL5.6后提出Online DDL。

早期DDL的明显缺点是,DDL时原表长时间只允许查询,不允许DML。为此,Mysql后来提出了Online DDL方法,通过细分各种DDL操作,从而支持部分DDL操作执行时不需要锁表,DDL 执行的过程中依然可以读写,不影响数据库对外提供服务。注意并不是所有DDL操作都支持在线操作:Online DDL分为两种方式,COPY TABLE和INPLACE,只有支持INPLACE方式的DDL操作才支持在线操作。

MySQL在线修改表结构的影响(MySQL Online DDL)

Online DDL分为三个执行阶段:prepare、execute、commit。

MySQL在线修改表结构的影响(MySQL Online DDL)

过程较为复杂,只需要注意row-log这个文件,它记录了DDL过程中原表上发生的写操作,它的作用是支持原表在DDL 期间可以正常提供写服务,只需要最后把row-log应用到新表上即可。

Online DDL可以有效改善DDL期间对数据库的影响:

  • Online DDL期间,查询和DML操作在多数情况下可以正常执行,减少锁表时间
  • 允许 inplace 操作的 DDL执行时,可以避免重建表格占用过多磁盘IO及CPU资源,减少数据库负荷。
  • COPY方式占用过多内存缓冲池(buffer pool),会导致内存部分频繁访问的数据被清理出去,使得DDL期间性能下降。而允许 inplace 操作的 DDL比需要COPY方式占用更少的内存,避免了性能的下降。

除了MySQL自带的Online DDL方式外,还有一些外部工具(比如PT-OSC和GH-OST等)可以做Online DDL,但是不是很重要,没必要去看了。