navicat 16保存表结构修改卡在“正在执行…”不是网络延迟或mysql慢,而是其合并ddl触发mysql元数据锁与内存瓶颈,需关闭预览、拆分操作、调高socket timeout及wait_timeout,并规避copy算法。
为什么“正在执行…”卡住不是网络问题
navicat 执行 alter table 时界面长时间显示“正在执行…”,通常不是连接慢或服务器卡,而是 mysql 正在等元数据锁(mdl),或者 navicat 自身在拼接、预检、缓存 ddl 语句时陷入阻塞。常见现象包括:show processlist 中看到状态是 waiting for table metadata lock,或执行 select count(*) 后直接挂起——这往往是 navicat 开启了「preview ddl」惹的祸。
- Navicat 默认会先执行
SELECT COUNT(*)来预估影响行数,但该查询会被长事务或未提交的SELECT阻塞 - 同时修改字段类型 + 加索引 + 改注释,Navicat 会合成一条
ALTER TABLE,MySQL 解析和内存分配压力陡增 - 哪怕服务端没断连,客户端 Socket Timeout 到期后主动断开,后台 DDL 仍在跑,造成“假死”错觉
必须同步调的三个超时参数
只改其中一项基本无效。Socket Timeout、keep-alive 心跳、wait_timeout 分属客户端、中间链路、服务端三层,缺一不可:
-
Socket Timeout(sec):右键连接 → Edit Connection → Advanced → 设为300(5 分钟)起步;千万级表建议设1800 - 勾选
Keep connection alive,间隔设为60(不能 >300,否则部分 NAT 设备丢心跳包) -
SET SESSION wait_timeout = 28800:填入 Advanced → SQL Query 框中,确保每次新建连接立即生效;SET GLOBAL不起作用,Navicat 不继承
DDL 卡住时怎么快速定位和清理
别等、别重试、别关 Navicat 窗口——进程关了,后台 DDL 还在跑。真正有效的是查锁、杀链、清残留:
- 执行
SHOW PROCESSLIST,重点看State列含metadata lock或Locked的行,记下Id - 查阻塞源头:
SELECT * FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(NOW()) - TIME_TO_SEC(TRX_STARTED) > 60,找长时间未提交的事务 - KILL 要杀整条等待链:不止是那条
ALTER TABLE,所有State为Waiting for table metadata lock的都得干掉 - 源库刚重启过?执行
FLUSH TABLES WITH READ LOCK; UNLOCK TABLES;强制刷新 MDL 缓存(需 SUPER 权限)
哪些操作必须放弃可视化,改手写 SQL
Navicat 的可视化编辑器对某些 DDL 天然不友好,强行点“保存”大概率触发 COPY 算法、全表锁、OOM 或 max_allowed_packet 报错:
- 主键变更、唯一索引重建、TEXT/BLOB 字段类型调整 —— 这些操作 MySQL 8.0 前默认用 COPY,全程锁表
- 加索引 + 改字段类型 + 更新表注释三合一 —— Navicat 拼成单条语句,易超内存限制,报
MySQL server has gone away - 给大表(>100 万行)加索引,尤其没加
ALGORITHM=INSTANT(MySQL 8.0.12+)时,别依赖界面按钮
复杂 DDL 的本质是 I/O 和锁竞争,不是配置能完全兜住的。真正省事的做法,是把变更拆成原子步骤、避开业务高峰、用 pt-online-schema-change 替代,而不是调高 timeout 后继续点“保存”。











