应先执行show status like 'innodb_row_lock_current_waits'初筛,返回值大于0即表示当前存在行锁等待;该方式轻量、低权限、响应快,适合线上高频轮询,但归零不代表问题消失,需结合innodb_row_lock_time_avg突增综合判断。

怎么快速确认当前有没有锁等待
先执行 SHOW STATUS LIKE 'innodb_row_lock_current_waits';。返回值大于 0,说明此刻就有事务卡在行锁上——这是最轻量、权限要求最低的初筛方式。
别等它“变多”才查:这个值归零不代表问题消失,可能只是锁刚释放,或等待刚好超时(默认 innodb_lock_wait_timeout=50 秒)。如果 innodb_row_lock_time_avg 突然从毫秒级跳到几十毫秒,基本可断定有慢事务或未提交事务在拖累。
- 普通账号也能查,适合线上随时拍快照
- 它不告诉你谁在等谁,只告诉你“有事发生”,是后续深入排查的触发信号
- 若为 0,但业务明显卡住,优先排查网络、I/O 或 SQL 执行本身是否过慢,而非直接断定“没锁”
怎么查出谁在等、谁在挡(MySQL 8.0 正确关联方式)
MySQL 8.0+ 已废弃 INNODB_LOCK_WAITS 和 INNODB_LOCKS,必须用 performance_schema.data_lock_waits,但它默认不采集数据,得先开开关:
确保采集器启用:SELECT NAME, ENABLED FROM performance_schema.setup_instruments WHERE NAME LIKE 'wait/lock/innoDB/%'; → 检查 wait/lock/innoDB/lock 是否为 YESUPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME IN ('global_instrumentation', 'thread_instrumentation');
然后执行关联查询(注意字段类型):SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_pid, r.trx_query waiting_query, b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_pid, b.trx_query blocking_query FROM performance_schema.data_lock_waits w JOIN information_schema.INNODB_TRX b ON b.trx_id = w.BLOCKING_ENGINE_TRANSACTION_ID JOIN information_schema.INNODB_TRX r ON r.trx_id = w.REQUESTING_ENGINE_TRANSACTION_ID;
-
BLOCKING_ENGINE_TRANSACTION_ID必须连INNODB_TRX.trx_id,不是trx_mysql_thread_id——后者是线程 ID,类型不一致会导致查不到结果 - 返回空 ≠ 没锁,可能是采集器没开、时机错过,或冲突已释放
- 该视图只记录“正在等待”的关系,锁一释放就消失,不具备历史回溯能力
怎么定位锁冲突的根因(不只是谁挡了谁)
看到阻塞链只是第一步。真正要解决,得回答三个问题:它为什么锁这么多?为什么不肯放?为什么别人非得等它?
重点查三件事:
- 对被阻塞的 SQL 执行
EXPLAIN,看type是否为ALL或index,key是否为NULL,rows是否远超预期——90% 的大面积锁冲突源于索引失效,比如WHERE phone = 13800138000(隐式转换)、DATE(create_time)(函数索引失效) - 查
performance_schema.data_locks,过滤LOCK_TYPE = 'RECORD'且LOCK_DATA大量重复或跨度极大(如从 1 到 5000),说明锁范围失控 - 查
INNODB_TRX中trx_state和trx_started:若状态是LOCK WAIT,说明它自己也被卡住了;若状态是RUNNING且trx_started是几分钟前,大概率是长事务忘了提交
为什么 SHOW ENGINE INNODB STATUS\G 不能跳过
它不是备选方案,而是必查项。因为 LATEST DETECTED DEADLOCK 区块里藏着无法被其他视图替代的关键线索:
被回滚的事务(ROLLING BACK 行)通常不是“问题方”,而是持有锁最少的那个;真正要盯的是两个事务的 lock_mode X locks gap before rec(间隙锁)还是 lock_mode X locks rec but not gap(精准行锁)——前者更容易引发交叉冲突。
- 每条 SQL 后面的锁模式和锁对象(如
PRIMARY, 123或idx_name, 'Eason')能帮你确认加锁是否符合预期 -
lock struct(s)下的lock_trx_id和lock_rec_lock可反向验证data_lock_waits中的事务 ID 是否真实持有对应锁 - 它还包含死锁检测时间、事务启动时间、隔离级别等上下文,这些在实时视图中往往缺失
复杂点在于:同一个事务可能同时持有多把锁、跨多个索引,而 data_locks 返回的是扁平化列表,不带事务内锁的逻辑分组。这时候,只有 SHOW ENGINE INNODB STATUS 里的原始结构能帮你理清“它到底锁了哪些东西、为什么锁”。











