加字段卡住时,先查是否被元数据锁(mdl)阻塞:执行select * from information_schema.innodb_trx where time_to_sec(now()) - time_to_sec(trx_started) > 60和show processlist,定位waiting for table metadata lock的线程并kill;避免navicat一键拼接alter语句触发copy算法,大表务必用pt-online-schema-change分批在线变更。
加字段卡住时,先查是不是被元数据锁(mdl)堵住了
navicat 点击“添加字段”后界面转圈不动,大概率不是网络问题,而是 mysql 正在等 metadata lock。只要表上有未提交的事务、长查询或排队中的其他 alter table,新 ddl 就会卡在 waiting for table metadata lock 状态。
立刻执行:
SELECT * FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(NOW()) - TIME_TO_SEC(TRX_STARTED) > 60;看有没有运行超 1 分钟的事务;再跑
SHOW PROCESSLIST;找状态含
Waiting for table metadata lock 的线程。别等它自己释放——MDL 等待是串行的,越拖越堵。别信 Navicat 的“可视化一键加字段”
Navicat 默认把加字段、改类型、设默认值、加注释全拼成一条 ALTER TABLE 语句。对大表来说,这等于主动触发 COPY 算法(尤其在 MySQL 5.7 或没显式指定 ALGORITHM=INSTANT 时),全程锁表、吃内存、易超 max_allowed_packet。
- 手动拆开:先
ALTER TABLE t ADD COLUMN x INT,再ALTER TABLE t MODIFY COLUMN x INT DEFAULT 0,最后ALTER TABLE t COMMENT='xxx' - MySQL 8.0.12+ 且字段不涉及类型变更时,强制用
ALGORITHM=INSTANT,例如:ALTER TABLE t ADD COLUMN y VARCHAR(32) ALGORITHM=INSTANT - Navicat 里关掉
Preview DDL before execution(Preferences → DDL),否则它会先跑SELECT COUNT(*)统计行数,反而加重 MDL 竞争
线上大表加字段,优先走 pt-online-schema-change
哪怕你确认没长事务、也用了 ALGORITHM=INSTANT,只要表行数过百万,风险就不可控。Navicat 的 GUI 操作无法控制 chunk 大小、无法跳过复制期间的主键冲突、也无法优雅降级。
真正稳妥的做法是切到命令行:
pt-online-schema-change --alter "ADD COLUMN z DATETIME" D=test,t=user --execute
它会自动建影子表、挂触发器、分批拷贝、原子切换。注意两点:
- 确保目标表有主键或唯一索引,否则
pt-osc会拒绝执行 - 执行前先
SET innodb_autoinc_lock_mode=2,避免高并发写入时因自增锁引发二次阻塞
加完字段别急着点“保存”,先验证锁是否真释放了
Navicat 界面显示“执行成功”不等于锁已释放。有些场景下(比如 ALGORITHM=COPY 后回滚失败),MDL 可能残留数分钟。最简单的验证方式是立刻执行一句 SELECT COUNT(*) FROM t LIMIT 1 —— 如果秒返回,说明锁已清;如果又卡住,说明后台还有未清理的元数据锁或隐式事务。
这时候别重试加字段,更别重启 Navicat。直接连上 MySQL,用 KILL 干掉 SHOW PROCESSLIST 里那些状态异常的线程,比反复点击“确定”有用得多。











