MySQL 5.7执行ALTER TABLE锁表是因默认全表重建并全程持有MDL_EXCLUSIVE锁,业务读写被硬性阻塞;持锁者多为未提交事务或Sleep连接,ALGORITHM=INPLACE不满足条件即报错而非降级,安全方案是pt-osc或升级8.0.12+ INSTANT DDL。

在MySQL 5.7中执行ALTER TABLE导致业务锁表,不是配置没调好、也不是SQL写得不对,而是该版本对绝大多数结构变更**默认走全表重建流程**,且全程强占元数据锁(MDL),业务读写被硬性阻塞——这是执行模型决定的不可避让行为。
为什么ALTER TABLE卡在Waiting for table metadata lock
这不是行锁或表数据锁,是元数据锁(MDL)。只要一个会话对某张表执行过任意语句(哪怕只是SELECT * FROM t),且事务未提交、连接未断开,它就持有MDL_SHARED_READ锁;而ALTER TABLE必须拿到MDL_EXCLUSIVE锁才能开始,二者互斥。
- 常见持锁者:应用连接池中长期
Sleep的连接(Time > 300、Info = NULL) - 开发/运维在终端执行
START TRANSACTION后关了窗口,事务仍活跃 - 监控脚本执行了未加事务控制的
SELECT,连接保持打开 -
SHOW PROCESSLIST看不到持锁者,真正有效的是:SELECT * FROM performance_schema.metadata_locks WHERE OBJECT_SCHEMA = 'db' AND OBJECT_NAME = 't'(MySQL 8.0+)或结合INNODB_TRX查长事务
ALGORITHM=INPLACE和LOCK=NONE为什么没用
它们不是免死金牌,MySQL 5.7 会严格校验是否真能就地执行,不满足条件就直接报错退出,不会静默降级为COPY模式。
-
ADD COLUMN末尾加字段且允许NULL、无DEFAULT值 → 可ALGORITHM=INPLACE - 同上但带
NOT NULL DEFAULT 'x'→ 必须全表回填,默认退化为COPY,即使写了ALGORITHM=INPLACE也无效 -
MODIFY COLUMN VARCHAR(255) → VARCHAR(1024)→ 在5.7中100%强制重建(长度头从1字节升为2字节) - 务必先执行:
EXPLAIN FORMAT=JSON ALTER TABLE t ...,确认输出中"alter_algorithm": "inplace"和"supports_inplace": true同时为真
为什么大表ALTER TABLE耗时几分钟甚至几十分钟
因为5.7实际执行的是:新建临时表 → 逐行拷贝原表数据(触发所有二级索引重建)→ 原子重命名。这个过程全程持有MDL_EXCLUSIVE锁,所有SELECT/INSERT/UPDATE/DELETE都被阻塞。
- 千万级表加一个
VARCHAR字段,实测锁表时间常达数分钟至数十分钟,取决于磁盘IO和CPU -
lock_wait_timeout默认是31536000秒(1年),所以你看到的不是报错,而是“卡住不动” - 长事务会让
MDL_EXCLUSIVE锁无限期等待——哪怕只是一个SELECT * FROM t FOR UPDATE没提交 -
innodb_lock_wait_timeout(默认50秒)只管行锁,对MDL完全无效
生产环境该怎么做才不崩
别赌ALGORITHM=INPLACE能跑通,也别在高峰期直接执行。关键动作是预判 + 隔离 + 替代。
- 先查长事务:
SELECT * FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(NOW() - trx_started) > 60 - 再查持锁连接:
SELECT * FROM performance_schema.metadata_locks WHERE OBJECT_SCHEMA = 'your_db' AND OBJECT_NAME = 'your_table'(8.0+) - 真正安全的方案只有两个:
pt-online-schema-change(推荐)或升级到MySQL 8.0.12+用INSTANT DDL -
pt-osc要求原表有主键或唯一非空索引;已有触发器的表不能用;禁止在从库单独运行再切主从(它不复制DDL)
最易被忽略的一点:EXPLAIN FORMAT=JSON输出里"lock": "none"为真,不代表整个过程零锁——末尾元数据切换阶段仍需短暂加MDL,高并发下可能引发排队雪崩。线上执行前,必须观察Seconds_Behind_Master波动和连接池使用率。


















