DDL是MySQL中最常见的变更动作,MySQL发展至今,DDL能力也在不断增强。本文主要介绍MySQL DDL能力的发展过程,常用的DDL操作说明,并给出AliSQL中DDL操作的优化和最佳实践。
MySQL 5.5及之前:仅支持COPY算法。 执行过程:先创建临时表,然后按行拷贝数据,最后表交换。 限制:DDL执行期间表只读,无法写入数据。 MySQL 5.6 & 5.7:支持INPLACE算法。 执行过程:引擎层处理DDL,无需临时表。 优势:DDL执行期间支持读写数据表。 限制:在DDL开始和结束时,可能会短暂锁表(不可读写),且会消耗临时空间。 MySQL 8.0、8.4:支持INSTANT算法。 执行过程:仅修改元数据,无需数据拷贝。 优势:秒级完成,显著缓解DDL对业务的影响。 限制:支持的DDL类型有限(加列、删列),在DDL开始和结束时,仍需要短暂持有表上的MDL X锁(不可读写)。 说明 所有算法均需在DDL的开始和结束阶段(上图阶段1和阶段3)获取MDL X锁,导致短暂锁表(不可读写),AliSQL对MDL锁等待进行了优化,详见AliSQL DDL相关优化功能。 MySQL支持在执行DDL操作时指定算法,若不指定,MySQL默认根据DDL操作类型选择最佳算法。以下为常见操作的执行逻辑及影响(默认InnoDB引擎)。 表操作 列操作 索引操作 特殊情况说明 DDL操作 DDL命令 默认算法及是否支持修改 DDL执行期间读写属性 可能影响说明 重命名表 RENAME 支持修改算法,默认值: 5.6、5.7:INPLACE 8.0、8.4:INSTANT 读写 仅修改元数据,无影响。 重建表 OPTIMIZE / ALTER ENGINE 不支持修改算法,5.6、5.7、8.0和8.4默认值:INPLACE。 读写 说明 AliSQL 8.0、8.4数据归档期间表只读不可写。 重建表会进行数据拷贝,需预留磁盘空间。 大表耗时长。 可能导致备库和只读实例复制延迟。 更新统计信息 ANALYZE 不支持修改算法。 读写 仅更新统计信息,但某些场景可能导致业务阻塞,详见特殊情况说明页签里的ANALYZE TABLE的阻塞场景。 修改字符集 CONVERT CHARSET 5.6、5.7不支持修改算法,默认值COPY。 8.0、8.4:支持修改算法,默认值COPY,仅特殊场景支持INPLACE,详见特殊情况说明页签里的修改字符集(CONVERT CHARSET)时使用INPLACE算法。 只读,无法进行写操作。 会拷贝数据到临时表,需预留磁盘空间。 大表耗时长。 可能导致备库和只读实例复制延迟。 修改表备注 ALTER COMMENT 不支持修改算法,5.6、5.7、8.0和8.4默认值:INPLACE。 读写 仅修改元数据,无影响。 从MySQL 5.7版本开始在 PFS加入了DDL相关Stage统计信息,可以通过processlist和P_S库下的events_stages_current表查看DDL进度,并且评估剩余时间。 适用场景:DDL执行中需实时监控进度。 查询语句: 说明 执行 示例:本地Sysbench 10 GB的表,查询结果 实际执行时间:2 min 3.14 s = 123.14 s 适用场景:无需开启PFS(消耗内存且会有性能影响,RDS MySQL默认关闭)的估算。 步骤: 云盘实例(高性能云盘和ESSD云盘):按照30~60 MB/s的速度进行估算。 高性能本地盘实例:按照50~100 MB/s的速度进行估算。 说明 30~60 MB/s和50~100 MB/s的速度是根据实例的IO能力估算的值,实际可能会有偏差。 查询表大小: 根据查询到的DATA_LENGTH大小,直接估算DDL的时间,以OPTIMIZE TABLE操作为例: (可选)索引影响:如果表存在很多二级索引,还需考虑二级索引排序和构建的时间,按主表速度的1/3估算索引构建时间。 示例:本地Sysbench 10 GB的表,查询结果如下: 实际执行时间:2 min 3.14 s = 123.14 s DDL是变更操作,尽量避开业务高峰。 支持INSTANT算法的DDL,或其他仅修改元数据的DDL,可以放心执行(为避免操作开始和结束阶段无法获取MDL X锁,仍需重点关注慢查询和大事务)。 只支持COPY算法的DDL,执行过程中表只读,无法进行写操作,需要谨慎执行。 其他支持INPLACE算法的DDL,执行过程中表可以读写,但是需要综合评估执行时间、空间占用,以及可能导致的复制延迟问题。 功能:异步清理大文件,避免文件系统抖动。 参数: 功能:减少DDL的执行耗时,降低DDL操作带来的性能影响。 参数: 功能:元数据变更,无需重建表。 参数: 其他优化 AHI清理优化:优化删除表和索引过程中AHI清理导致的性能问题。参数:innodb_rds_drop_ahi_ahead,默认为OFF。 唯一索引冲突优化:优化DDL期间唯一索引冲突导致DDL失败的问题。 MDL锁等待逻辑优化:将MDL X锁的阻塞式等待优化为非阻塞式等待,解决了DDL长期拿不到MDL锁导致业务面积性阻塞的问题。 ANALYZE TABLE优化:解决了MySQL 5.7 版本ANALYZE TABLE可能导致业务阻塞的问题。 Parallel DDL:修复DDL性能回退问题。 升级至AliSQL最新版本以获取全部优化功能DDL能力发展

MySQL常用DDL操作说明
DDL执行时间评估
方式一:基于Performance Schema(PFS)评估
SELECT * FROM information_schema.processlist WHERE ID = <替换为实际ID>;SELECT THREAD_ID, EVENT_ID, EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED,(WORK_COMPLETED/WORK_ESTIMATED)*100 AS PROGRESS
FROM performance_schema.events_stages_current WHERE THREAD_ID = <替换为实际ID>;
SHOW Processlist命令根据执行的SQL获取ID。TIME=116,PROGRESS=83.9961%,如下图所示:
计算时间 = TIME / PROGRESS = 116 / (83.9961%) = 138.1 s
方式二:基于表空间大小评估
SELECT * FROM information_schema.tables WHERE TABLE_SCHEMA = <替换为实际的数据库名> AND TABLE_NAME = <替换为实际的表名>;

计算时间 = DATA_LENGTH / 1024 / 1024 / 100 + INDEX_LENGTH / 1024 / 1024 / 100 * 3 = 10270785536 / 1024 / 1024 / 100 + 665829376 / 1024 / 1024 / 100 * 3 = 117 s
AliSQL DDL最佳实践
基本原则
AliSQL DDL相关优化功能
innodb_data_file_purge=ON(默认开启)。loose_innodb_rds_faster_ddl=ON(需手动开启)。loose_innodb_instant_ddl_enabled=ON(MySQL 8.0版本默认开启,5.7及以下版本需手动开启)。相关文档