MySQL 在线表结构变更实践

6次阅读

mysql在线表结构变更的核心目标是不锁表、不影响业务读写,其实际效果取决于操作类型、存储引擎、版本及参数配置;innodb表上添加/删除二级索引、增大varchar长度、重命名列/索引等通常支持algorithm=inplace且lock=none,而修改主键、设not NULL、缩小varchar长度等则需重建表并全表锁。

MySQL 在线表结构变更实践

MySQL 在线表结构变更(Online DDL)的核心目标是:不锁表、不影响业务读写、变更过程平滑。从 MySQL 5.6 开始原生支持部分 Online DDL 操作,到 5.7 和 8.0 持续增强,但并非所有 ALTER table 都真正“在线”,实际效果取决于操作类型、存储引擎(InnoDB)、版本及参数配置。

哪些变更能真正在线执行

在 InnoDB 表上,以下常见操作通常支持 ALGORITHM=INPLACELOCK=NONE(即不阻塞 DML):

  • 添加/删除二级索引(不含主键)
  • 修改列的定义(如 VARCHAR 长度增大、调整 COMMENT)——前提是不触发行格式变更或数据重写
  • 重命名列(RENAME column)或索引(RENAME INDEX)
  • 添加生成列(Generated Column)或虚拟列
  • 修改 ROW_FORMAT、KEY_BLOCK_SIZE(需满足存储引擎约束)

注意:即使支持 INPLACE,某些操作仍可能短暂需要 LOCK=SHARED(允许读、阻塞写),例如修改列默认值(ALTER COLUMN … SET default)在 8.0+ 中已优化为无锁,但旧版本仍需谨慎验证。

哪些操作必须重建表(高风险)

以下变更会触发 ALGORITHM=copy 或强制 LOCK=EXCLUSIVE,导致全表拷贝、长时间锁表,严禁在大表上直接执行:

  • 修改主键(ADD/ DROP/ CHANGE PRIMARY KEY)
  • 将列设为 NOT NULL(若该列存在 NULL 值,需全表扫描修正)
  • 缩小 VARCHAR 长度(如 VARCHAR(255) → VARCHAR(50),可能截断,需校验数据)
  • 修改列类型(如 int → BIGINT 在 5.7+ 支持 INPLACE,但 TINYINT → INT 仍可能触发 COPY)
  • 添加自增列(ADD COLUMN auto_increment)

执行前务必用 ALTER TABLE … ALGORITHM=INPLACE, LOCK=NONE 显式指定并观察是否报错;若提示 “ALGORITHM=INPLACE is not supported”,说明必须重建表。

安全变更的实操建议

生产环境执行前应遵循最小干扰原则:

  • 先查执行计划:运行 ALTER TABLE tbl_name ... ALGORITHM=INPLACE, LOCK=NONE; 测试语法与可行性,不加 FORCE,让 MySQL 自动判断
  • 监控变更过程:通过 SHOW PROCESSLIST 观察状态,配合 performance_schema.table_lock_waits_summary_by_table 查锁等待
  • 大表优先用 pt-online-schema-change:当原生 Online DDL 不适用时,Percona Toolkit 的 pt-osc 通过影子表+触发器实现无锁变更,但需额外磁盘空间和注意主从延迟
  • 避开业务高峰 + 设置超时:用 innodb_lock_wait_timeout 控制等待时间,避免长事务阻塞 DDL;变更期间暂停定时任务或批量导入
  • 验证后再上线:变更后检查 SHOW CREATE TABLE、索引是否生效、应用查询是否走新索引、慢日志有无新增异常

MySQL 8.0 的重要改进

相比 5.7,8.0 对 Online DDL 进一步放宽限制:

  • 支持 原子性 DDL(crash-safe),避免表结构与数据不一致
  • 多数 SET DEFAULTDROP DEFAULT 操作不再锁表
  • ADD COLUMN 默认在末尾追加,无需重建表(除非指定 FIRST/AFTER)
  • 支持 ALTER TABLE ... RENAME COLUMN 语法,比旧版 CHANGE COLUMN 更安全
  • INFORMATION_SCHEMA.INNODB_TABLES 新增 ALGORITHM 字段,可追溯历史 DDL 执行方式

升级到 8.0 后,建议统一使用 ALGORITHM=INSTANT(适用于纯元数据变更,如加列、改注释),速度极快且完全无锁。

text=ZqhQzanResources