数据库内核月报

数据库内核月报 - 2023 / 09

云原生数据库PolarDB MySQL 8.0.2 DDL介绍

Author: yinggang

引言

众所周知,在MySQL生态下,DDL是一类非常复杂的操作,涵盖了Index变更、Primary Key变更、Column列结构变更、Table表结构变更、Foreign Key操作、Generated Column列结构变更等多种不同类型的操作。DDL不仅持续时间久、消耗硬件资源多,而且其中涉及的锁表操作更成为了很多用户的梦魇,操作不慎就可能导致影响正常业务,造成灾难性的影响。
云原生数据库PolarDB MySQL在DDL方面经过多年的经验积累和持续的功能迭代,目前在性能和锁稳定性方面取得了长足的进步。本文将基于PolarDB MySQL 8.0.2版本,介绍不同类型DDL的执行方式,供用户查询了解,以期帮助用户了解DDL的行为,评估DDL操作风险,降低对业务的影响。对于DDL操作,本文主要从如下几个方面展开介绍。

Index操作

操作 允许并发DML 重建表 秒级完成 支持并行DDL
创建二级索引 支持
删除二级索引 不需要
重命名二级索引 不需要
增加全文索引
(FULLTEXT)
1 不支持
增加空间索引 (SPATIAL) 不支持
修改索引类型 不需要
  1. 在添加表上第一个全文索引时,如果没有用户定义的FTS_DOC_ID列,会导致额外的重建表操作。

Primary Key操作

操作 允许并发DML 重建表 秒级完成 支持并行DDL
增加Primary Key 支持
删除Primary Key 不支持
删除原来Primary Key,
增加新的Primary Key
支持

Column操作

操作 允许并发DML 重建表 秒级完成 支持并行DDL
增加列 1 1 支持1
删除列 支持
重命名列 不需要
重排序列 支持
设置列的默认值 不需要
修改列类型 不支持
扩展VARCHAR长度 2 不需要
删除列默认值 不需要
修改auto-increment值 不需要
变更某列为NULL 支持
变更某列为非NULL 支持
修改ENUM/SET列的定义 不需要
  1. 秒级加列仅支持添加列到表的末尾,并且表需要已有主键(否则可能会因为最末尾的隐式主键导致Instant Add Column失败)。另外,Instant Add Column不支持压缩表(ROW_FORMAT=COMPRESSED),不支持全文索引的表,不支持临时表。如果不支持Instant Add Column,增加列默认走INPLACE DDL,需要全表重建。此时支持通过并行DDL加速,允许并发DML。
  2. 扩展VARCHAR长度:存储VARCHAR列长度所需的字节数需要保持一致,才能支持快速修改。具体来说,对于0-255Bytes的VARCHAR列,只需要一个Byte存储长度。而对于大于等于256Bytes的VARCHAR列,就需要两个Bytes存储长度。只有控制VARCHAR列长度的扩展范围,比如从0-255Bytes,或者从256Bytes到更大的范围,才能支持ALTER TABLE只修改元数据。也就是说,当修改VARCHAR列长度从小于256Bytes到大于256Bytes的长度时,PolarDB默认走Copy DDL类型,即全程都是锁表的,不支持DML写操作,仅支持读操作。当用户不确定自己修改VARCHAR列的范围是否满足上述条件时,可以手动执行DDL的执行方式为INPLACE。此时,如果不支持快速列扩展,会直接报错。如下给出了一个参考示例:
ALTER TABLE table_name ALGORITHM=INPLACE, CHANGE COLUMN c1 c1 VARCHAR(256);

ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot change
column type INPLACE. Try ALGORITHM=COPY.

varchar类型属于变长存储类型,磁盘仅存储实际长度,因此建议用户在使用varchar字段时,考虑将最大长度直接调整到256以上,避免扩展字段时可能需要走copy算法。

Table操作

操作 允许并发DML 重建表 秒级完成 支持并行DDL
修改ROW_FORMAT 支持
修改KEY_BLOCK_SIZE 支持
设置持久化统计信息 不需要
声明character set 1 支持
转换character set 不支持
Optimize表 2 支持
重建表 支持
重命名表 不需要
  1. 如果新的character发生变化,需要走COPY DDL重建表的方式
  2. 通过ALTER TABLE table_name ENGINE=InnoDB, ALGORITHM=INPLACE, LOCK=NONE,重新整理表中的碎片时,带全文索引的表不支持INPLACE。

Generated Column操作

操作 允许并发DML 重建表 秒级完成 支持并行DDL
增加STORED Column 1 不支持
修改STORED Column顺序 不支持
删除STORED Column 支持
增加VIRTUAL Column 不需要
修改VIRTUAL Column顺序 不支持
删除VIRTUAL Column 不需要
  1. 由于增加Stored Column表达式涉及SQL/Server层,因此不支持Online DDL。

Foreign Key操作

操作 允许并发DML 重建表 秒级完成 支持并行DDL
增加Foregin Key 1 1 1 不需要
删除Foregin Key 1 1 1 不需要
  1. 只有关闭了foreign_key_checks开关情况下,才支持INPLACE DDL,并且只修改元数据。否则只支持COPY DDL,全程锁表。

分区表操作

操作 允许并发DML 秒级完成 In Place 支持并行DDL
表转分区 不支持
增加分区(ADD) 1 2 不支持
删除分区(DROP) 1 2 不支持
删除分区表空间(DISCARD) 不支持
导入分区表空间(IMPORT) 不支持
截断分区(TRUNCATE) 不支持
合并分区(HASH/KEY分区) 3 不支持
重分布分区(REORGNIZATE 1 3 不支持
交换分区(EXCHANGE) 1 不支持
分析分区(ANALYZE) 不支持
检查分区(CHECK) 不支持
优化分区(OPTIMIZE) 不支持
重建分区(REBUILD) 1 3 不支持
修复分区(REPAIR) 不支持
分区转表 不支持
  1. 支持分区级元数据锁,开启loose_partition_level_mdl_enabled参数后,DDL不影响不涉及的分区上的DML。更多信息可以参考:PolarDB的在线分区维护功能[3]
  1. 只有RANGE/LIST分区支持。
  2. 只支持QUERY。

总结

由于篇幅原因,本文仅介绍了部分常见的DDL操作,希望能够帮助用户在执行DDL前,了解相关DDL在云原生数据库PolarDB MySQL 8.0.2版本上的行为特征。总的来说,经过多年的持续优化,借助于并行DDL、Instant DDL、DDL IO优化等方面的工作,PolarDB MySQL在DDL方面已经形成了较大的优势。未来,PolarDB内核团队将继续在DDL方面发力,进一步提升DDL的易用性,始终如一地为用户打造最佳的云原生数据库。

参考资料:

[1] PolarDB的并行DDL功能:https://help.aliyun.com/zh/polardb/polardb-for-mysql/user-guide/parallel-ddl
[2] 深度解析PolarDB DDL锁的优化和演进:https://mp.weixin.qq.com/s/icYkCqEPboIlx9UxPr5ZnQ
[3] PolarDB的在线分区维护功能:https://help.aliyun.com/zh/polardb/polardb-for-mysql/user-guide/online-partition-maintenance