navicat结构比对卡在“读取对象”阶段,大概率是目标库被长事务持有mdl锁阻塞;需查innodb_trx定位超60秒事务,再通过innodb_lock_waits确认锁等待链,避免盲目kill,优先联系业务方确认事务可终止性。
navicat结构比对卡在“读取对象”阶段,大概率是目标库被长事务锁住了
navicat 在执行「结构同步」或「数据库对比」时,第一步就是批量执行 show full columns from `table_name`、show create table、show create view 等语句来拉取元数据。如果某个表正被一个未提交的事务长时间持有 mdl(metadata lock),后续所有需要访问该表结构的语句都会阻塞——navicat 就会卡在“读取对象”不动,光标转圈,连接无响应,但 mysql 服务端其实还在等锁释放。
怎么快速确认是不是长事务在锁表
别猜,直接查 INNODB_TRX 和 INNODB_LOCK_WAITS:
- 先看有没有运行超 60 秒的活跃事务:
SELECT * FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(NOW()) - TIME_TO_SEC(TRX_STARTED) > 60; - 再查锁等待链:
SELECT * FROM information_schema.INNODB_LOCK_WAITS;—— 如果有结果,说明已有阻塞发生 - 重点看
TRX_MYSQL_THREAD_ID和TRX_QUERY,确认那个长事务是不是业务导入、ETL 脚本或手动开启却忘了COMMIT的调试会话
别急着 kill,先判断事务是否可中断
直接 KILL 长事务看似解气,但风险很高:
- 如果它是正在写入订单流水的事务,
KILL可能导致部分数据回滚、状态不一致 - 某些 ORM(如 Django/SQLAlchemy)会在连接池里复用 session,
KILL后应用层可能报MySQL server has gone away并反复重连 - 更稳妥的做法是:联系对应业务方确认该事务是否可终止;若确认安全,再执行
KILL <code>TRX_MYSQL_THREAD_ID
临时缓解:调高会话级超时,但治标不治本
如果你只是要跑完这一次比对,且确定目标库没有关键长事务,可以临时放宽限制:
- 在 Navicat 当前连接中手动执行:
SET SESSION innodb_lock_wait_timeout = 300; - 同时检查 Navicat 连接属性 → 高级 → 「自动提交事务」是否勾选;没勾的话,每个查询都默认开启事务,容易意外积累未提交操作
- 注意:这不能解决锁源问题,只是让 Navicat 多等一会儿,等锁自然释放或被其他机制清理
真正卡住的从来不是 Navicat 的界面,而是它背后那条被 MDL 死死咬住的 SQL。每次卡在“读取对象”,第一反应不该是重启软件或换电脑,而是去 INNODB_TRX 里翻一翻——谁还拿着锁没松手。











