不能。SHOW OPEN TABLES仅显示表是否被缓存及In_use状态,不提供锁持有者PID、SQL或等待信息;需结合performance_schema.metadata_locks、INNODB_TRX和PROCESSLIST定位具体锁表进程。

show_open_tables 能不能查出表锁进程?
不能。SHOW OPEN TABLES 只显示当前被缓存(open)的表,以及是否被其他线程“加锁”(In_use 列非 0),但它**不提供持有锁的进程 ID、SQL、等待状态等任何上下文信息**。你看到 In_use = 1,只知道“有线程正在用这张表”,但不知道是谁、在干什么、卡在哪——这根本没法定位死锁或长事务。
真正能查到锁表进程的命令是哪些?
MySQL 5.7+ 推荐直接查 performance_schema 或 information_schema 的锁视图,配合 PROCESSLIST 关联分析:
-
SELECT * FROM performance_schema.metadata_locks WHERE OBJECT_SCHEMA = 'db_name' AND OBJECT_NAME = 'table_name';—— 查元数据锁(MDL),显示OWNER_THREAD_ID,再关联performance_schema.threads就能得到PROCESSLIST_ID -
SELECT * FROM information_schema.INNODB_TRX WHERE trx_mysql_thread_id IN (SELECT THREAD_ID FROM performance_schema.metadata_locks WHERE OBJECT_NAME = 'table_name');—— 查持锁的 InnoDB 事务详情(SQL、运行时长、状态) -
SHOW PROCESSLIST;或SELECT * FROM information_schema.PROCESSLIST WHERE ID IN (…);—— 定位具体线程,看State是否为Waiting for table metadata lock或Updating等可疑状态
为什么 show open tables 的 In_use 值经常误判?
In_use 不代表“正在执行 DML”,它只是表示该表对象在表缓存中被某个线程引用计数 > 0。常见误触发场景:
- 一个事务里执行了
SELECT,还没提交,In_use就可能为 1(尤其开启innodb_locks_unsafe_for_binlog时) - 使用了
LOCK TABLES ... WRITE后未UNLOCK TABLES,表会一直显示In_use = 1,但此时实际锁已由显式锁机制接管,和 MDL 无关 - 查询过程中临时打开表(如派生表、子查询物化),
In_use短暂为 1,但几毫秒后就归零——你刷得再快也抓不到
快速定位锁表进程的一条实用命令链
把上面逻辑串起来,一行可执行(替换 your_db 和 your_table):
SELECT p.ID, p.USER, p.HOST, p.DB, p.COMMAND, p.TIME, p.STATE, p.INFO FROM information_schema.PROCESSLIST p JOIN performance_schema.metadata_locks m ON p.ID = m.OWNER_THREAD_ID WHERE m.OBJECT_SCHEMA = 'your_db' AND m.OBJECT_NAME = 'your_table' AND m.LOCK_DURATION = 'TRANSACTION';
注意:LOCK_DURATION = 'TRANSACTION' 是关键过滤条件,排除掉语句级短暂锁;如果查不到结果,说明不是 MDL 锁,可能是行锁(查 INNODB_LOCK_WAITS)或表级 FLUSH TABLES WITH READ LOCK 这类全局锁。
真正麻烦的从来不是“怎么查”,而是查到之后发现那个线程正卡在磁盘 I/O 或外部 API 调用上——这时候 kill 掉它,得先确认上游业务是否允许中断。


















