Navicat不管理MDL锁,阻塞源于MySQL内核;需通过SHOW PROCESSLIST定位State含“Waiting for table metadata lock”的等待者、Command为Query且Info含DDL/DML的持锁者,以及Time长的Sleep连接,并依次KILL等待队列、持锁线程和INNODB_TRX中RUNNING超5分钟的事务。
navicat 本身不管理元数据锁(mdl),所有阻塞都来自 mysql 内核层——你看到的 waiting for table metadata lock 不是 navicat 的 bug,而是它在安静地等 mysql 释放锁;杀错线程、只 kill ddl、忽略隐式事务,都会让问题反复出现。
别依赖 Navicat 界面默认的“活动监视器”全量刷新,它可能漏掉刚挂起的 Sleep 连接。直接进命令行执行:
SHOW PROCESSLIST;
盯三列:State、User、Info:
State 含 Waiting for table metadata lock 的,全是等待者,不是源头State 是 Query 或 Updating,且 Time > 30 秒,Info 显示 ALTER TABLE / CREATE INDEX / SELECT ... FOR UPDATE 的,大概率是持锁者User 为 navicat 或空值,基本可断定是 Navicat 自身发起但未提交的操作(比如点过「保存修改」后关了窗口)Command 是 Sleep 但 State 是空、Info 为空、且 Time 很长的连接——这往往是隐式事务没提交,正安静地持有 MDLMySQL 的 MDL 锁绑定在事务上,不是语句上。一个 SELECT 或 UPDATE 开启了事务但没 COMMIT,只要碰过目标表,就可能长期持有写锁。DDL 被 KILL 后,回滚过程本身还要短暂持锁,而所有等待者仍在队列里——等于点了引信,没拆弹。
必须一次性处理整条链:
State = 'Waiting for table metadata lock' 的会话(清空等待队列)State = 'Query' 且 Info 显示 DDL 或长时间 DML 的持锁线程INFORMATION_SCHEMA.INNODB_TRX,过滤 TRX_STATE = 'RUNNING' 且 TRX_STARTED 超 5 分钟的事务,对应 KILL 其 TRX_MYSQL_THREAD_ID
SHOW PROCESSLIST,避免误判锁已释放Navicat 的「保存修改」按钮本质是拼一条完整 ALTER TABLE 执行,不拆解、不降级、不提示风险——它把最危险的操作当成了最简单的点击。
真正可控的做法是绕过可视化:
pt-online-schema-change 替代原生操作FLUSH TABLES tbl_name;(替换为实际表名),强制刷新该表元数据缓存,比等自动释放更可靠最容易被忽略的点:Navicat 界面里看不见那些隐式开启又没提交的 SELECT,它们安静地躺在后台,像一根随时会引爆的引信——查 INNODB_TRX 比盯着 SHOW PROCESSLIST 更早发现隐患。