源库重启后navicat同步卡在waiting for table metadata lock,主因是mdl锁状态未清理、残留事务未回滚及binlog位点错乱;需执行flush tables with read lock+unlock tables清锁,查innodb_trx定位并kill幽灵事务,人工对齐binlog位点,且务必先flush status和flush tables刷新元数据缓存。
源库重启后 navicat 同步卡在 waiting for table metadata lock
mysql 源库意外重启后,navicat 同步常卡死在 waiting for table metadata lock 状态——这不是同步脚本本身出错,而是 mysql 重启时未正确清理残留的 mdl 锁状态,导致后续 dml/ddl 仍被旧锁阻塞。此时 show processlist 可能看不到明显异常进程,但锁实际还挂在表元数据上。
真正有效的动作不是等、不是重试,而是强制刷新 MDL 缓存:
- 先执行
FLUSH TABLES WITH READ LOCK;,再立刻执行UNLOCK TABLES;—— 这会清空所有未释放的表级 MDL 引用(注意:该操作需 SUPER 权限,且会短暂阻塞写入) - 若权限不足,改用
FLUSH TABLES tbl_name;(替换tbl_name为同步涉及的具体表名),对单表触发元数据重载 - 避免直接
KILL进程:重启后很多线程 ID 已失效,KILL会返回 “Unknown thread id”,无效且浪费时间
同步任务自身因连接中断残留事务未回滚
Navicat 同步使用长事务搬运数据,源库重启会导致客户端连接断开,但 MySQL 可能未及时标记该事务为“已终止”,其持有的行锁或间隙锁仍存在,造成目标库写入时触发死锁环。
必须主动查出这些“幽灵事务”并终结:
- 运行
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TRX_STATE = 'RUNNING' AND TRX_STARTED —— 找出启动超 5 分钟、但当前无活跃连接的事务 - 结合
SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID IN (SELECT TRX_MYSQL_THREAD_ID FROM INFORMATION_SCHEMA.INNODB_TRX WHERE ...);验证线程是否真实存活;若INFO列为空或USER为NULL,基本可判定是残留 - 对确认残留的
TRX_MYSQL_THREAD_ID,执行KILL(不是KILL QUERY),强制释放锁资源
重启后 binlog 位点错乱引发同步逻辑冲突
源库重启可能造成 binlog 文件切换不完整,或 gtid_executed 记录滞后,导致 Navicat 同步内部比对时误判数据差异,反复尝试更新同一行,加剧锁竞争。
此时不能依赖界面重试,要人工对齐状态:
- 在源库执行
SHOW MASTER STATUS;,记录当前File和Position(或Executed_Gtid_Set) - 检查 Navicat 同步日志中最后成功同步的位点,若明显落后于
SHOW MASTER STATUS输出,说明有跳跃或丢失 - 放弃当前同步任务,在 Navicat 中新建同步,并勾选
Compare by primary key only(而非全字段比对),减少条件扫描引发的锁范围 - 若启用 GTID,务必确保目标库
gtid_purged包含源库重启前的全部集合,否则同步会拒绝启动
为什么调隔离级别或重连配置都没用
源库重启引发的锁问题,本质是服务端元数据状态不一致,不是客户端行为可控的范畴。把 Transaction Isolation Level 改成 READ COMMITTED、重置 Navicat 连接池、甚至换新连接字符串,全都不影响 MDL 锁残留或事务未回滚这两个底层事实。
最容易被忽略的一点是:MySQL 重启后,INFORMATION_SCHEMA 视图缓存可能未刷新,导致 INNODB_TRX 或 PROCESSLIST 返回过期结果。务必在执行任何 KILL 前,先运行 FLUSH STATUS; 和 FLUSH TABLES;,否则你看到的“无异常”只是假象。











