直接查innodb_trx和innodb_lock_waits并关联processlist可精准定位阻塞者与被阻塞者及对应sql:trx_state='lock wait'表示正等待锁,'running'且trx_started过长(>2分钟)或trx_query为空则多为未提交的长事务;blocking_trx_id指向阻塞源,需结合trx_mysql_thread_id匹配processlist.id查真实语句,注意mdl锁等非行锁场景不在此链路中。

直接查 INNODB_TRX 和 INNODB_LOCK_WAITS,再关联 PROCESSLIST,就能定位谁在阻塞、谁被卡住、执行的是哪条 SQL —— 不需要猜,也不依赖 SHOW ENGINE INNODB STATUS 那种难解析的文本块。
查 INNODB_TRX 找出“卡着不动”的事务
真正拖慢数据库的不是某条 SQL,而是没提交/没回滚的事务。优先看这个表:
-
TRX_STATE = 'LOCK WAIT'表示它正等着拿锁,大概率已被阻塞 -
TRX_STATE = 'RUNNING'但TRX_STARTED时间很早(比如 > 2 分钟),说明是长事务,可能正拿着锁不放 -
TRX_QUERY字段为空?别急——可能是事务刚BEGIN就挂了,也可能是 SQL 已执行完但事务仍开着 - 记下
TRX_MYSQL_THREAD_ID,这是后续 kill 或查 SQL 的关键 ID
用 INNODB_LOCK_WAITS 看清“谁在等谁”
这个视图是锁等待链的唯一直接来源,但它只保留瞬时快照,必须在卡顿发生时立刻查:
- 字段
BLOCKING_TRX_ID对应阻塞方的事务 ID,WAITING_TRX_ID是被阻塞方 - 拿
BLOCKING_TRX_ID去INNODB_TRX查,就能定位到那个“锁源事务” - MySQL 8.0+ 中
INNODB_LOCKS已被移除,不要依赖它;改用performance_schema.data_locks(需提前开启) - 如果
INNODB_LOCK_WAITS返回空,不代表没锁——可能锁已释放,或根本没走到等待阶段(比如 MDL 锁不走这个路径)
通过 SHOW FULL PROCESSLIST 抓真实 SQL
INNODB_TRX.TRX_QUERY 经常为空或截断,得靠线程级信息补全:
- 用
TRX_MYSQL_THREAD_ID匹配PROCESSLIST.Id,找到对应行 - 重点看
Info字段:它显示当前正在执行(或最后执行)的语句,但 ORM(如 PDO 开启ATTR_EMULATE_PREPARES = true)可能导致真实语句藏在预处理逻辑里 -
State是Locked或持续增长的Updating,大概率卡在锁或 I/O;Command = Sleep但Time很大(> 60),说明连接拿了不放,事务可能还挂着 - 注意:
SHOW PROCESSLIST默认只显示前 100 条,务必用SHOW FULL PROCESSLIST防止漏掉关键连接
区分 MDL 锁和行锁,避免误判
不是所有“卡住”都来自 InnoDB 行锁。常见混淆点:
- 如果
PROCESSLIST.State显示Waiting for table metadata lock,说明是元数据锁(MDL)阻塞,跟INNODB_TRX无关,得查sys.schema_table_lock_waits或performance_schema.metadata_locks -
Waiting for table flush通常由FLUSH TABLES WITH READ LOCK或长查询阻塞FLUSH引起,也不是行锁问题 - 行锁等待(如
SELECT ... FOR UPDATE被UPDATE阻塞)才会体现在INNODB_LOCK_WAITS;MDL 锁不会 - 死锁发生后,InnoDB 自动回滚一个事务,但残留的等待可能还在
INNODB_TRX里显示为RUNNING,需结合时间戳判断是否已失效
真正容易被忽略的是:阻塞源头可能早已断开连接(比如应用 crash),但事务没自动 rollback(autocommit 关闭 + 没显式 commit),这时 PROCESSLIST 里看不到它,INNODB_TRX 却还留着——这种“幽灵事务”只能靠 TRX_STARTED 时间 + 应用日志交叉验证。











