MySQL表结构变更真正“在线”需综合操作类型、版本能力、参数配置与运行负载:ADD COLUMN带默认值可无锁,NOT NULL无默认值则强制COPY;VARCHAR长度修改须保持字节编码不变才支持INPLACE;大表需调优innodb_online_alter_log_max_size等参数,并优先在从库验证,5.7建议用pt-osc,8.0.12+可用INSTANT。

MySQL 表结构变更要真正“在线”,不能只靠加 ALGORITHM=INPLACE, LOCK=NONE 就完事。实际效果取决于操作类型、版本能力、参数配置和运行时负载。优化核心是:选对算法、控住日志、避开陷阱、留足资源。
看懂操作类型,决定是否真能“无锁”
不是所有 ADD COLUMN 都一样。MySQL 对不同变更的处理方式差异极大:
- 添加
NULL列(带默认值):5.7+ 默认 INPLACE,几乎不锁表,适合高频业务表 - 添加
NOT NULL列且无默认值:必须扫描全表填充,强制 COPY,全程锁写 - 添加
NOT NULL DEFAULT x列:5.7 中仍需重建,8.0 起部分场景支持 INSTANT(仅改元数据) - 修改列类型(如
VARCHAR(100) → VARCHAR(200)):若字节编码不变(≤255 或 ≥256),可 INPLACE;否则降级为 COPY - 添加二级索引:典型 INPLACE-NO_REBUILD 场景,只写索引页,DML 可并发
关键参数必须调优,尤其大表场景
默认参数在高并发下极易出问题。重点关注:
-
innodb_online_alter_log_max_size:默认 128MB,但大表 + 高频 DML 下日志可能溢出导致失败。建议按预估变更时间 × 每秒 DML 量 × 平均日志条目大小估算,设为 512MB 或更高 -
innodb_sort_buffer_size:影响索引构建速度,大表建索引时可临时调至 4–8MB(注意全局内存压力) -
lock_wait_timeout:避免 DDL 卡在 MDL 等待上太久,建议设为 30–60 秒并配合重试逻辑 - 执行前检查
performance_schema.metadata_locks,确认无长事务或 DDL 冲突
版本与工具要匹配真实需求
别迷信“Online”三个字,得看版本能力和业务容忍度:
- MySQL 5.7:INPLACE 支持有限,
MODIFY COLUMN多数需重建;建议优先用pt-online-schema-change(pt-osc)处理复杂变更 - MySQL 8.0.12+:支持 INSTANT DDL(如增删列、改列名),毫秒级完成,但仅限特定操作;原子 DDL 还能防崩溃不一致
- 超大表(亿级)或强一致性要求场景:pt-osc 或 gh-ost 更稳妥——它们绕过原生限制,但需额外磁盘、主从延迟可控、禁用外键/触发器
- gh-ost 要求 binlog_format=ROW 且 row_image=FULL(5.6 必须手动改,5.7+ 默认满足)
生产执行前必须做的几件事
跳过检查,等于把风险直接交给线上:
- 先在从库或影子环境回放相同 DDL,观察执行时间、CPU、IO 和慢查询日志
- 确认表有主键或非空唯一键(gh-oss/pt-osc 强依赖)
- 暂停定时任务、ETL 导入、批量更新等写入高峰操作
- 设置低峰期窗口(如凌晨 2–4 点),并预留 2–3 倍预估时间作为缓冲
- 用
SHOW PROCESSLIST和information_schema.innodb_trx监控长事务,DDL 前 kill 掉阻塞源


















