最快初筛innodb锁等待应执行show status like 'innodb_row_lock_current_waits';,返回值>0表示当前有行锁等待;配合innodb_row_lock_time_avg突增可判断持续阻塞,该方式轻量、低权限、响应快。

查InnoDB当前有没有锁等待(最快初筛)
别一上来就查大表,先执行 SHOW STATUS LIKE 'innodb_row_lock_current_waits';。返回值 > 0 表示此刻有事务正卡在行锁上——这是最轻量、权限要求最低、响应最快的判断方式。
搭配看 innodb_row_lock_time_avg:如果它从毫秒级突然跳到几十毫秒以上,说明不是偶发抖动,而是已有持续性阻塞。
- 这个状态变量普通账号就能查,适合高频轮询或告警脚本
- 归零不等于问题消失——可能刚释放,也可能等待超时(默认
innodb_lock_wait_timeout=50秒) - 它只反映“当前是否有等待”,不告诉你谁在等、等了多久
定位InnoDB谁在等、谁在挡(MySQL 8.0+ 正确关联)
MySQL 8.0+ 已废弃 INNODB_LOCK_WAITS,查它永远为空。必须用 performance_schema.data_lock_waits 关联 INNODB_TRX,但前提是得先开采集开关。
先确认锁 instrument 是否启用:SELECT NAME, ENABLED FROM performance_schema.setup_instruments WHERE NAME LIKE 'wait/lock/innoDB%';,确保相关项为 YES;再打开消费者:UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME IN ('global_instrumentation', 'thread_instrumentation');
- 关键查询中,
BLOCKING_ENGINE_TRANSACTION_ID必须连INNODB_TRX.trx_id,不能误连trx_mysql_thread_id(类型不一致,必查不到) - 阻塞链是瞬时的,查不到≠没锁,可能是你查的时机晚了半秒
- 若仍无结果,检查是否漏开了
wait/lock/innoDB/lock这类具体 instrument
算InnoDB当前等待了多久(不是平均值)
别信 innodb_row_lock_time_avg,那是自实例启动以来所有等待的累计平均值,单位毫秒,和“现在卡了几秒”完全无关。
真正能算出“当前等了多久”的字段是 INNODB_TRX.trx_wait_started(MySQL 5.7+ 引入),类型为 DATETIME。执行这条语句即可获得秒级等待时长:
SELECT trx_id, trx_mysql_thread_id, trx_query, UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(trx_wait_started) AS wait_seconds FROM INFORMATION_SCHEMA.INNODB_TRX WHERE trx_state = 'LOCK WAIT';
- 结果为空 ≠ 没锁等待,可能事务已超时回滚、或刚释放
- 普通账号默认查不到其他用户事务,需授予
PROCESS权限,否则只看到自己线程,极易误判 -
trx_wait_started在事务未进入LOCK WAIT状态前为 NULL,所以 WHERE 条件必须写严
MyISAM 根本没有“锁等待耗时”这回事
MyISAM 没事务、没行锁、没等待队列,它的锁是表级、阻塞式、不可中断的。所谓“等待”,只是操作系统线程挂起,MySQL 不记录任何开始时间。
执行 SHOW OPEN TABLES WHERE In_use > 0 只表示该表正被某个线程打开并持有读/写锁——但你无法知道这个锁持有了多久、谁在等、等了多久。
-
In_use=1对 MyISAM 表甚至可能只是个简单SELECT,不代表有问题 - 监控重点不是“耗时”,而是
Key_reads / Key_read_requests比值:超过0.01就说明key_buffer_size不够,索引缓存失效导致频繁磁盘读,这才是拖慢的根本原因 - 想确认是否损坏,必须用
CHECK TABLE table_name;,返回status: OK才算健康
实际排查时最容易忽略的是权限与采集开关:没 PROCESS 权限就看不到别人事务,没开 performance_schema 的 lock instrument 就查不到阻塞链——这两点卡住的人最多。











