mysql 5.6+ add column 默认用inplace算法,满足条件时不全程锁表,但受引擎、列位置、类型、默认值及algorithm/lock参数影响;推荐algorithm=inplace+lock=none,大表建议用pt-online-schema-change。

ALTER TABLE ADD COLUMN 会锁表吗?
MySQL 5.6+ 默认使用 INPLACE 算法执行 ADD COLUMN,只要满足条件就不会全程锁表——但“不锁表”不等于“无影响”。实际行为取决于存储引擎、列位置、数据类型、是否含默认值,以及你显式指定的 ALGORITHM 和 LOCK 策略。
ALGORITHM=INPLACE vs ALGORITHM=COPY 怎么选?
ALGORITHM=INPLACE 是在线 DDL 的核心,它复用原表空间,只修改元数据和少量行数据(如新增列的默认值填充),速度快、锁粒度小;ALGORITHM=COPY 则重建整张表,期间表不可写,且需要双倍磁盘空间。生产环境必须优先尝试 INPLACE,但以下情况会自动降级或报错:
- 在
ADD COLUMN时指定AFTER xxx(非末尾加列),且表使用ROW_FORMAT=COMPACT/REDUNDANT:MySQL 5.7.26+ 才支持 INPLACE - 新增列为
TEXT/BLOB且表有全文索引:不支持INPLACE - 使用
ALGORITHM=INPLACE但未指定LOCK:MySQL 可能仍要求LOCK=NONE才允许执行,否则报错ER_ALTER_OPERATION_NOT_SUPPORTED
如何安全执行 ADD COLUMN?关键参数组合
生产环境执行前务必验证当前 MySQL 版本与表结构兼容性,并用最小权限账号操作。推荐命令模板如下:
ALTER TABLE `orders` ADD COLUMN `refund_reason` VARCHAR(255) DEFAULT NULL AFTER `status`, ALGORITHM=INPLACE, LOCK=NONE;
说明:
-
LOCK=NONE表示不允许任何 DML 阻塞(即 SELECT/INSERT/UPDATE/DELETE 全部允许),这是真正“在线”的前提;若提示不支持,可降级为LOCK=SHARED(允许读,阻塞写),但需评估业务写入窗口 - 避免在
ADD COLUMN同时加索引或改列类型——复合操作大概率触发COPY,应拆成独立语句 - 对大表(>10GB 或 >1 亿行),即使
INPLACE成功,也可能因逐行填充默认值引发 I/O 尖峰,建议搭配pt-online-schema-change做灰度验证
容易被忽略的隐性坑
很多人以为只要没报错就万事大吉,但这些细节常在上线后暴露:
- 新增列带
DEFAULT值时,MySQL 不会立刻写入所有行——首次访问某行才 lazy 初始化该列值。这导致SELECT COUNT(*)结果不变,但SELECT * FROM t WHERE new_col IS NOT NULL可能漏数据 - 如果表启用了
innodb_file_per_table=OFF,INPLACE操作仍可能触发系统表空间增长,监控ibdata1大小变化 -
ALGORITHM=INPLACE在主从复制中表现一致,但某些旧版本从库(如 5.6.20 之前)可能将该 DDL 记为STATEMENT格式并失败,需确认binlog_format=ROW且从库版本 ≥ 主库
最稳妥的做法不是赌参数,而是先在影子库上跑 EXPLAIN FORMAT=JSON 查看执行计划里的 alter_algorithm 和 lock_type 字段,再决定是否上生产。











