核心思考问题:新增字段一定会锁表吗?
答案:不一定!这主要取决于:
- MySQL 版本: 这是最关键的因素。
ALGORITHM选项: 显式或隐式指定的算法。- 新增字段的属性: 是否允许 NULL?是否有默认值?默认值类型?字段位置?
- 表的大小和存储引擎: InnoDB 的行为与 MyISAM 不同(本文主要讨论 InnoDB)。
- 并发负载: 操作期间对表的读写压力。
一、真实案例场景:血泪教训
场景1:电商大促前夜,核心订单表加字段(MySQL 5.5)
-
操作:
ALTER TABLE orders ADD COLUMN coupon_id INT NOT NULL DEFAULT 0;

-
结果:
- 千万级订单表,执行耗时 45分钟。
- 整个过程中,下单、支付接口全部阻塞,业务瘫痪。
- 数据库连接池耗尽,大量应用报
Lock wait timeout exceeded。
-
原因: MySQL 5.6 及之前版本:锁表重灾区。
-
机制: 这些版本主要使用
COPY算法执行ADD COLUMN。- MySQL 会创建一个与原表结构相同(包含新字段)的新表。
- 将原表数据逐行复制到新表中(此时会计算和应用新字段的默认值)。
- 在复制过程中,原表通常会被施加 Metadata Lock (MDL) 写锁(在复制开始前获取,直到结束才释放)。
- 复制完成后,进行原子性的
RENAME操作,将新表替换旧表,并删除旧表。
-
影响:
- 长时间阻塞: 在复制数据的整个过程中(可能持续数秒、数分钟甚至数小时,取决于表大小和服务器性能),原表上的所有写操作(INSERT, UPDATE, DELETE)以及大部分读操作(SELECT … FOR UPDATE, LOCK IN SHARE MODE)都会被阻塞。普通的
SELECT在操作开始前已获取 MDL 读锁的可以继续,但新的SELECT也可能在等待锁。 - 服务中断: 对于写密集型的核心业务表,这会导致应用大面积报错(如锁等待超时
Lock wait timeout exceeded),用户体验急剧下降,甚至业务停滞。 - 主从延迟: 在主从复制环境中,主库执行耗时的大表加字段操作,会导致从库应用该 DDL 时也产生相同的阻塞,进而造成严重的复制延迟。
- 资源消耗: 复制过程需要额外的磁盘空间(容纳新表)和大量的 I/O、CPU 资源,可能影响其他数据库操作。
- 长时间阻塞: 在复制数据的整个过程中(可能持续数秒、数分钟甚至数小时,取决于表大小和服务器性能),原表上的所有写操作(INSERT, UPDATE, DELETE)以及大部分读操作(SELECT … FOR UPDATE, LOCK IN SHARE MODE)都会被阻塞。普通的
场景2:社交平台用户表加简介字段(MySQL 5.7,未指定算法)
-
操作:
ALTER TABLE users ADD COLUMN bio VARCHAR(200) DEFAULT NULL AFTER nickname;

-
结果:
- 虽然使用了 5.7,但指定了
AFTER位置且未明确算法。 - 操作使用了
INPLACE但需要 重建表 (Rebuild Table),阻塞写操作 8秒。 - 高峰期导致 Feed流发布短暂卡顿,用户投诉激增。
- 虽然使用了 5.7,但指定了
-
原因: 加字段在中间位置触发了表重建,
INPLACE的准备/提交阶段持有锁。 -
MySQL 5.7 及更新版本:Online DDL 带来曙光 (但非绝对无忧)
-
机制: MySQL 5.6 后期引入了 Online DDL 的概念,并在 5.7 及 8.0 中不断完善。对于
ADD COLUMN,在满足特定条件下,可以使用INPLACE甚至INSTANT算法。-
INPLACE算法:- 不需要重建整个表。大多数情况下,只需修改表的元数据(
.frm文件或 InnoDB 数据字典)并在表的末尾(逻辑上)添加新字段。 - 虽然避免了全表数据复制,但在操作的开始和结束阶段(准备阶段和提交阶段)仍需要短暂的 MDL 写锁。这个时间通常很短(毫秒到秒级)。
- 关键点: 在操作的主体阶段(应用阶段),允许对表进行并发读写操作(DML) 。这是避免长时间阻塞的核心改进。
- 影响: 短暂阻塞(准备/提交) + 主体阶段并发读写。虽然比
COPY好得多,但如果表非常大或系统负载极高,短暂的锁仍可能被感知到,且主体阶段的并发 DML 可能因为内部 row log 应用而略微变慢。
- 不需要重建整个表。大多数情况下,只需修改表的元数据(
-
INSTANT算法 (MySQL 8.0.12+):-
这是最理想的方案!仅修改元数据。
-
操作瞬间完成(毫秒级),只需要非常短暂的 MDL 写锁。
-
影响: 几乎可以忽略不计的阻塞。对业务透明性最高。
-
限制: 并非所有
ADD COLUMN都支持INSTANT。主要限制有:- 新列必须加在所有已有列的最后(
AFTER指定位置不行)。 - 不能是
FULLTEXT,SPATIAL索引的一部分。 - 不能是
STORED GENERATED COLUMN。 - 不能用于压缩表。
- 不能是
DATETIME(2),TIME(2),TIMESTAMP(2)等包含小数秒精度的列(在 8.0.29 之前有更多限制)。 - 不能有
AUTO_INCREMENT属性。 - 不支持
ALTER TABLE ... ALGORITHM=INSTANT, ADD COLUMN ...后立即ADD INDEX(需要分开操作)。
- 新列必须加在所有已有列的最后(
-
-
-
Online DDL 的潜在影响 (即使使用 INPLACE/INSTANT):
- 空间增长:
INPLACE操作可能需要在表空间内部重建部分结构或维护 row log,会占用额外的临时磁盘空间。INSTANT通常只增加元数据大小。 - 复制延迟: 即使主库很快完成,从库(尤其是配置较弱的从库)应用 DDL 时也可能产生延迟,特别是大表。
- 性能波动:
INPLACE操作在应用阶段,后台应用 row log 时可能会消耗 I/O 和 CPU,对高并发负载产生轻微影响。 - MDL 锁冲突: 如果操作前已有长时间运行的查询持有 MDL 读锁,
ALTER TABLE获取 MDL 写锁会被阻塞,导致后续所有需要 MDL 锁的查询被阻塞(连锁反应)。
- 空间增长:

最低0.47元/天 解锁文章
905

被折叠的 条评论
为什么被折叠?



