Mysql-场景篇-2-线上高频访问的Mysql表,如何在线修改表结构影响最小?-1--Mysql8.0版本后的INSTANT DDL方案(推荐)
MySQL 8.0引入的INSTANT DDL(即时DDL)是一种高效的在线DDL操作方式,旨在通过最小化资源消耗和锁表时间,实现对表结构的快速修改,同时保持对业务的低影响。
1、INSTANT DDL的核心特点
(1)无需复制数据
- 传统DDL的问题:
在MySQL 8.0之前,大多数DDL操作(如添加字段、修改列类型)需要创建临时表,将原表数据复制到临时表,再通过表名交换完成修改。这一过程会消耗大量磁盘空间和I/O资源,且锁表时间较长。 - INSTANT DDL的改进:
INSTANT DDL不复制数据,仅修改表的元数据(如列定义、索引信息),从而将操作时间从分钟级缩短到毫秒级。
(2)原子性与事务支持
- INSTANT DDL操作是原子的,即操作要么完全成功,要么完全回滚,不会导致数据不一致。
- 通过事务日志(如Redo Log和Binlog)保障崩溃恢复时的数据一致性。
(3)几乎无锁表
- 锁表时间极短:
INSTANT DDL在执行过程中仅在准备阶段(创建元数据)和提交阶段(更新数据字典)短暂持有表级锁,锁表时间通常小于1秒。 - 允许并发DML:
在修改元数据的过程中,允许用户对表进行读写操作(如SELECT、INSERT、UPDATE、DELETE),业务几乎无感知。
2、INSTANT DDL的工作原理
INSTANT DDL的核心是元数据管理和默认值填充机制,具体实现如下:
(1)元数据版本管理
- 表元数据版本:
MySQL 8.0为表维护了一个元数据版本号(TOTAL_ROW_VERSIONS),每次INSTANT DDL操作后版本号递增。 - 行数据解析:
当查询历史数据时,MySQL会根据数据对应的元数据版本号,动态解析行数据。例如:- 如果某行数据缺少新添加的列,会用默认值填充。
- 如果某列被删除,该列的数据在查询时会被忽略。
(2)默认值填充
- 新增列的默认值:
INSTANT DDL要求新增列必须定义默认值(如DEFAULT ‘abc’),以便在查询历史数据时填充缺失的列值。
sql示例:
ALTER TABLE users ADD COLUMN new_col VARCHAR(255) DEFAULT 'default_value' ALGORITHM=INSTANT;
解释:
主要通过在DDL语句后添加ALGORITHM=INSTANT实现。
- 原表中的现有行在查询时会自动显示new_col的默认值,而无需实际写入磁盘。
(3)物理存储优化
- 新增列的位置:
INSTANT DDL添加的列始终位于表的最后(MySQL 8.0.29后支持指定位置)。 - 磁盘数据布局:
行数据的物理存储结构保持不变,新增列的值仅在插入新行时写入磁盘。
3、支持的DDL操作类型
INSTANT DDL并非支持所有DDL操作,目前主要支持以下类型:
4、锁表行为分析
INSTANT DDL的锁表行为分为两个阶段:
(1)准备阶段(Prepare Phase)
- 锁表时间:短暂持有表级锁(毫秒级)。
- 操作内容:
- 修改表的元数据(如新增列定义)。
- 更新数据字典(如mysql.tables、mysql.columns)。
- 对业务影响:
- 所有DML操作(如SELECT、INSERT)会被短暂阻塞。
(2)执行阶段(Execution Phase)
- 锁表时间:无需锁表。
- 操作内容:
- 对新增列的默认值进行持久化存储。
- 更新事务日志(Redo Log和Binlog)。
- 对业务影响:
- 允许并发执行DML操作。
(3)提交阶段(Commit Phase)
- 锁表时间:短暂持有表级锁(毫秒级)。
- 操作内容:
- 提交事务并清理中间状态。
- 对业务影响:
- 所有DML操作会被短暂阻塞。
5、性能优势与适用场景
(1)性能优势
(2)适用场景
- 高频表结构变更:如微服务架构中频繁迭代的业务需求。
- 大表在线变更:如用户表、日志表等数据量巨大的场景。
- 高可用性要求:如金融、电商等不允许停机的业务。
(3)限制条件
- 不支持的操作:
- 修改主键或外键。
- 添加全文索引或空间索引。
- 修改列的存储引擎(如从MyISAM切换到InnoDB)。
- 版本限制:
- MySQL 8.0.12仅支持ADD COLUMN。
- MySQL 8.0.29新增支持DROP COLUMN。
- 存储引擎限制:
- 仅支持InnoDB存储引擎。
6、实际应用示例
(1)添加列
sql示例:
-- MySQL 8.0.12+支持
ALTER TABLE users ADD COLUMN email VARCHAR(255) DEFAULT 'no_email@example.com' ALGORITHM=INSTANT;-- MySQL 8.0.29+支持指定列位置
ALTER TABLE users ADD COLUMN age INT DEFAULT 18 ALGORITHM=INSTANT AFTER name;
(2)删除列
sql示例:
-- MySQL 8.0.29+支持
ALTER TABLE users DROP COLUMN old_column ALGORITHM=INSTANT;
(3)修改默认值
sql示例:
-- 修改列的默认值
ALTER TABLE users ALTER COLUMN status SET DEFAULT 'active' ALGORITHM=INSTANT;
7、总结
- INSTANT DDL的核心价值:
通过元数据管理和默认值填充机制,实现毫秒级表结构变更,且几乎不影响业务。 - 适用性:
适用于需要频繁修改表结构、数据量大、对锁表时间敏感的场景。 - 注意事项:
- 仅支持部分DDL操作(如ADD COLUMN、DROP COLUMN)。
- 需确保MySQL版本>= 8.0.12(或8.0.29以支持DROP COLUMN)。
- 不支持修改主键、外键或添加全文索引。
尽管Instant DDL提供了减少锁表时间的能力,但在进行任何DDL操作前,了解具体的变更需求以及评估潜在的风险是非常重要的。此外,在生产环境中应用这些变更之前,建议先在测试环境中进行全面测试。
总之,MySQL 8.0后的Instant DDL特性为高效管理数据库结构提供了一种强有力的新工具,特别是在需要频繁且快速地适应变化的应用场景中。