跳转到内容

大表变更

用途:给亿级表加列、加索引、改类型而不锁业务

算法 是否阻塞 DML 说明
COPY 是 全表复制到新表,锁写,旧版本方式
INPLACE 多数不阻塞 在引擎内构建新结构(加索引、部分列变更)
INSTANT 否 仅改元数据(8.0 加列到末尾、改默认值等),秒级完成

语法:ALTER TABLE t ADD COLUMN c INT, ALGORITHM=INSTANT; 明确指定算法可让不满足条件的变更直接报错,而不是悄悄退化成锁表。

  1. 元数据锁 MDL:变更需要拿到排他 MDL;若有长查询或未提交事务持读锁,DDL 排队并阻塞后续所有新查询(雪崩式)。
  2. 临时空间与日志:加索引需要排序与大量 redo,可能撑爆磁盘并放大复制延迟。
  3. 表重建:改主键、改字符集、改列类型需要重建整表。
手段 说明
低峰执行 + lock_wait_timeout 小值 拿不到 MDL 就快速失败,不拖垮业务
先杀长事务 变更前后检查 information_schema.innodb_trx
在线改表工具 gh-ost(binlog 驱动,无触发器)、pt-online-schema-change(触发器 + 影子表):复制数据→追增量→原子改名
分批 DDL 分区表可按分区做;大索引创建可拆多列
从库先行 在从库执行再切换(部分工具支持),避免主库阻塞
回滚预案 影子表保留期与改名回退步骤
  • 加列优先于改列:新增列 + 双写 + 回填 + 切读,比原地改类型安全得多。
  • 字符集/排序规则变更是重建级操作,必须专项评估(含索引长度与唯一性语义变化)。
  • 索引变更注意唯一索引冲突会导致失败;先清理脏数据。
  • 变更脚本必须幂等,失败可重跑;所有 DDL 进版本库与评审。
误区 修正
以为 8.0 有 INSTANT 就都秒完成 只有特定操作是 INSTANT,改类型仍重建
高峰期“就加个索引” 加索引会重建二级结构并产生大量 IO 与 redo
DDL 卡住就 kill 连接 回滚可能比执行更久,需评估
不做从库延迟观察 大 DDL 常导致分钟级延迟,影响读流量
依赖 ALGORITHM 默认行为 显式指定,让不满足条件的语句失败而不是锁表
  • MySQL 官方文档:Online DDL、innodb_online_alter_log_max_size
  • GitHub gh-ost、Percona pt-online-schema-change 文档