这三条命令是 MySQL 锁问题排查的「三板斧」,掌握它们能快速定位绝大多数锁相关的性能问题和故障:
show open tables where in_use>0;
SELECT * FROM information_schema.INNODB_TRX\G;
show engine innodb status\G;
一、show open tables where in_use>0; —— 查看被占用的表(表级锁
这条命令用于查看当前正在被使用(持有表锁) 的表,in_use>0 表示表被至少一个会话占用(读锁 / 写锁),常用于排查「表被锁住导致 SQL 执行卡住」的问题。
典型输出:

字段说明:
Database:数据库名;Table:表名;In_use:占用该表的会话数(1表示 1 个会话占用,2表示 2 个会话同时占用);Name_locked:表名是否被锁定(0= 未锁定,1= 锁定,通常为 0,仅在重命名 / 删除表时会触发)。
实战场景
- 当执行
ALTER TABLE/DROP TABLE卡住时,用这条命令排查是否有会话占用该表; - 结合
show processlist;可进一步找到占用表的会话 ID,进而 kill 掉阻塞的会话。
二、SELECT * FROM information_schema.INNODB_TRX\G; —— 查看活跃事务(行级锁)
查询 InnoDB 引擎下所有未提交的活跃事务,包括事务 ID、执行的 SQL、持有的锁、阻塞状态等,是排查「行级锁阻塞」「长事务」的核心命令(\G 用于格式化输出,比表格更易读)。
典型输出:
*************************** 1. row ***************************
trx_id: 123456 -- 事务ID(唯一标识)
trx_state: RUNNING -- 事务状态(RUNNING/LOCK WAIT等)
trx_started: 2026-01-23 10:00:00 -- 事务启动时间(排查长事务)
trx_requested_lock_id: NULL -- 若为LOCK WAIT,此处显示等待的锁ID
trx_wait_started: NULL -- 等待锁的开始时间(LOCK WAIT时非空)
trx_weight: 2 -- 事务权重(影响死锁时的回滚选择)
trx_mysql_thread_id: 123 -- 对应的MySQL会话ID(可结合show processlist)
trx_query: UPDATE user SET name='test' WHERE id=1 -- 事务执行的SQL
trx_operation_state: NULL -- 事务当前操作状态
trx_tables_in_use: 1 -- 事务中使用的表数量
trx_tables_locked: 1 -- 事务锁定的表数量
trx_lock_structs: 1 -- 事务持有的锁结构数量
核心字段重点:
核心字段重点
trx_state:RUNNING:事务正常运行(未提交);LOCK WAIT:事务正在等待锁(被其他事务阻塞);
trx_started:若时间很久(如几小时),说明是长事务,易导致锁堆积;trx_mysql_thread_id:找到阻塞的会话 ID 后,执行kill 123;可终止事务;trx_query:直接看到导致锁的 SQL 语句,快速定位问题。
三、show engine innodb status\G; —— 查看 InnoDB 状态(含死锁日志)
输出 InnoDB 引擎的完整状态信息,包括最近一次死锁的详细记录、事务统计、锁等待、缓冲池状态等,是排查「死锁」的核心命令(MySQL 默认只保留最近一次死锁记录)。
关键输出:死锁记录解读
执行命令后,找到 LATEST DETECTED DEADLOCK 段(最近死锁),示例:
------------------------
LATEST DETECTED DEADLOCK
------------------------
2026-01-23 10:10:00 0x7f1234567890
*** (1) TRANSACTION:
TRANSACTION 123456, ACTIVE 10 sec updating
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 123, OS thread handle 140702345678900, query id 789 localhost root updating
UPDATE user SET balance = balance - 100 WHERE id = 1; -- 事务1执行的SQL
*** (1) WAITING FOR THIS LOCK TO BE GRANTED: -- 事务1等待的锁
RECORD LOCKS space id 123 page no 45 n bits 72 index PRIMARY of table `test`.`user` trx id 123456 lock_mode X waiting -- 等待行级排他锁(X锁)
*** (2) TRANSACTION:
TRANSACTION 123457, ACTIVE 15 sec updating
mysql tables in use 1, locked 1
2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 124, OS thread handle 140702345679000, query id 790 localhost root updating
UPDATE user SET balance = balance + 100 WHERE id = 1; -- 事务2执行的SQL
*** (2) HOLDS THE LOCK(S): -- 事务2持有的锁
RECORD LOCKS space id 123 page no 45 n bits 72 index PRIMARY of table `test`.`user` trx id 123457 lock_mode X -- 持有行级排他锁(X锁)
*** (2) WAITING FOR THIS LOCK TO BE GRANTED: -- 事务2也在等待锁(死锁核心)
RECORD LOCKS space id 123 page no 45 n bits 72 index PRIMARY of table `test`.`user` trx id 123457 lock_mode X waiting
*** WE ROLL BACK TRANSACTION (1); -- MySQL选择回滚事务1(权重小的)
死锁解读关键点
TRANSACTION 1/2:两个互相阻塞的事务;WAITING FOR THIS LOCK:事务等待的锁类型(X 锁 = 排他锁,S 锁 = 共享锁);HOLDS THE LOCK(S):事务持有的锁;WE ROLL BACK TRANSACTION (1):MySQL 自动回滚其中一个事务以解除死锁;- 核心原因:两个事务互相持有对方需要的锁,且都不释放。
四、实战排查流程(锁 / 死锁问题)
当数据库出现 SQL 卡住、执行缓慢或报死锁错误时,按以下步骤排查:
- 第一步:查被占用的表
show open tables where in_use>0;→ 确认是否有表被长期占用; - 第二步:查活跃事务
SELECT * FROM information_schema.INNODB_TRX\G;→ 找到长事务、阻塞的事务 ID 和 SQL; - 第三步:查死锁记录
show engine innodb status\G;→ 若有死锁,定位死锁的事务和 SQL; - 第四步:处理问题
- 长事务 / 阻塞事务:
kill 会话ID;(如kill 123;); - 死锁:优化 SQL(如调整更新顺序、缩小锁范围、加索引),避免互相锁。
- 长事务 / 阻塞事务:
死锁记录保留:MySQL 仅保留最近一次死锁记录,若需监控所有死锁,需开启死锁日志:
# my.cnf 配置
innodb_print_all_deadlocks = 1 # 开启所有死锁日志,记录到error log
Categories:
数据库运维