alter table在大表上锁表阻塞读写,主因是多数操作触发全表重建(copy算法),全程持mdl写锁与表级锁,阻塞所有dml;即使inplace也需短暂mdl,长事务或高并发下仍会排队等待、引发雪崩。

因为大表上 ALTER TABLE 不只是“改个结构”,它大概率会触发全表重建、锁表、IO风暴,甚至引发主从延迟、连接池耗尽、服务雪崩——这些不是理论风险,是线上高频事故。
ALTER TABLE 在大表上为什么会锁表或阻塞读写?
MySQL 的 ALTER TABLE 本质是元数据变更 + 物理结构调整。对千万级表来说,多数操作仍需走 COPY 算法(尤其在 MySQL 5.6 之前或某些字段类型变更场景):
-
ADD COLUMN若带NOT NULL且无DEFAULT,InnoDB 必须为每行填充值 → 触发全表扫描 + 行更新 → 锁升级为LOCK=SHARED或更严 -
MODIFY COLUMN即使只改默认值,只要用MODIFY或CHANGE,MySQL 就会重建表(哪怕只是改.frm文件也能搞定) - 即使启用
ALGORITHM=INPLACE,若涉及索引重建、页分裂、B+树重排,仍会持有MDL(metadata lock),阻塞后续 DDL/DML
为什么 Online DDL 也不能完全放心?
MySQL 5.7+ 的 ALGORITHM=INPLACE, LOCK=NONE 确实大幅降低影响,但有硬性前提和隐性代价:
- 仅对特定操作支持真正无锁:比如
ADD COLUMN且类型兼容、允许NULL、有DEFAULT值;一旦加NOT NULL且没默认值,立刻退化为锁表 -
LOCK=NONE≠ 零影响:高并发下 DML 会排队等待 MDL,表现为慢查询堆积、Waiting for table metadata lock状态飙升 - 主库执行时,从库复制仍需重放 DDL 事件;如果 DDL 耗时长,从库延迟可能从秒级跳到分钟级,影响读一致性与备份恢复点
- 临时文件 + redo log + binlog 爆增,可能触发磁盘满、IO饱和,连带拖慢其他表操作
真实线上最容易踩的三个坑
不是“会不会出问题”,而是“什么时候出、怎么爆得最狠”:
-
误判版本行为:在 MySQL 5.7 上对大表跑
ALTER TABLE ... ADD COLUMN xxx INT NOT NULL,以为能LOCK=NONE,结果卡住 20 分钟——实际因NOT NULL无默认值,强制退回到COPY模式 -
忽略隐式锁竞争:DDL 执行中,应用层大量
INSERT ... ON DUPLICATE KEY UPDATE请求持续涌入,每个都需抢 MDL,导致连接池快速耗尽,报错Too many connections -
低估日志压力:单次
ALTER生成数 GB binlog,压垮从库 IO 或填满max_binlog_size,触发日志轮转失败,进而阻塞所有写入
大表结构变更从来不是“执行一条 SQL”的事,关键在预判锁类型、验证 INFORMATION_SCHEMA.INNODB_TRX 和 PROCESSLIST 实时状态、监控从库 Seconds_Behind_Master 波动——这些动作比语法本身更重要。











