之前的学习中,一出现锁问题,我们都会通过一下两个命令之一来检测事务中的锁问题:

SHOW ENGINE INNODB STATUS;
SHOW FULL PROCESSLIST;

其实,MySQL为我们提供了更好的工具去记录和检测锁问题。大家还记得我们的数据库里有一个 information_schema数据库吗?

展示我的数据库集合

该数据库下面有3个重要的表(实际只有一张,其他两张已弃用),分别是:INNODB_TRXINNODB_LOCKS(已弃用) 和 INNODB_LOCK_WAITS (已弃用) ,用于监控和诊断 InnoDB 引擎中锁与事务状态的系统表,常统称为 InnoDB 锁监控表。它们揭示了事务如何持有或等待锁,是排查锁等待和死锁问题的核心工具。

通过一张表格让大家简要理解一下这三张表:


表名核心作用关键字段/说明状态
INNODB_TRX提供当前所有活跃事务的详细信息。trx_id: 事务ID
trx_state: 事务状态 (e.g., RUNNINGLOCK WAIT)
trx_started: 事务开始时间
trx_mysql_thread_id: 关联的客户端连接ID
trx_query: 正在执行的SQL
仍有效
INNODB_LOCKS显示当前事务已持有或正在申请的锁信息。lock_id: 锁ID
lock_trx_id: 持有锁的事务ID
lock_mode: 锁模式 (e.g., XS)
lock_type: 锁类型 (RECORD or TABLE)
lock_table: 被锁定的表
已弃用 (MySQL 5.7+)
已移除 (MySQL 8.0+)
INNODB_LOCK_WAITS揭示锁等待的阻塞关系。requesting_trx_id请求锁(被阻塞)的事务ID
blocking_trx_id持有锁(阻塞他人)的事务ID
已弃用 (MySQL 5.7+)
已移除 (MySQL 8.0+)

下面举个例子说明这么查看INNODB_TRX表格:

犯错会吧:

准备两个窗口A、B;

有这么一张dotcpp_user表格:

dotcpp_user表格

进入A窗口,此时我们开启事务并对id>2的进行查询并“上锁”:

BEGIN;
SELECT * FROM dotcpp_user WHERE  id>2 FOR UPDATE;

对于Id>2的用户进行查询并上锁

进入B窗口,开启事务并插入一个新用户,(5,'dotcpp_user05','完全二叉树'),此时就等50s吧:

锁等待

切换information_schema数据库后我们直接开始看表:

先看这张表INNODB_TRX:

mysql> select * from innodb_trx \G
*************************** 1. row ***************************
                    trx_id: 2432
                 trx_state: RUNNING
               trx_started: 2025-09-17 17:36:33
     trx_requested_lock_id: NULL
          trx_wait_started: NULL
                trx_weight: 2
       trx_mysql_thread_id: 46
                 trx_query: NULL
       trx_operation_state: NULL
         trx_tables_in_use: 0
         trx_tables_locked: 1
          trx_lock_structs: 2
     trx_lock_memory_bytes: 1128
           trx_rows_locked: 3
         trx_rows_modified: 0
   trx_concurrency_tickets: 0
       trx_isolation_level: REPEATABLE READ
         trx_unique_checks: 1
    trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
 trx_adaptive_hash_latched: 0
 trx_adaptive_hash_timeout: 0
          trx_is_read_only: 0
trx_autocommit_non_locking: 0
       trx_schedule_weight: NULL
1 row in set (0.00 sec)

各参数解释如下:

字段解释与分析
trx_id事务ID:这个事务的内部编号是2432。
trx_state状态最重要! 状态是RUNNING,说明它是活跃的。它可能是阻塞者,而不是被阻塞者(如果是LOCK WAIT就是被阻塞了)。
trx_started开始时间:这个事务已经开始运行了。可以根据这个时间判断它是不是一个“长事务”。
trx_requested_lock_id等待的锁非常好! 这里是NULL,表示这个事务没有在等待任何锁。它没有被其他事务阻塞。
trx_mysql_thread_id连接ID非常关键! 这个ID可以直接关联到 SHOW PROCESSLIST 中的 Id下一步马上就用这个。
trx_query当前SQL:为NULL表示事务当前没有在执行任何SQL语句。它处于“空闲”状态,很可能在等待应用程序发送下一条命令(比如 COMMIT)。
trx_rows_locked锁定行数:这个事务已经锁定了3行数据。这就是它可能成为“阻塞者”的原因。
trx_rows_modified修改行数为0,表示这个事务还没有执行过 UPDATE/DELETE/INSERT 等修改操作。它是一个只读事务(但FOR UPDATE读也会加锁)。

同时,我们通过SHOW FULL PROCESSLIST 语句查看MySQL当前所有的连接状态。该语句通常用来处理突发事件,返回的结果是实时变化的。

mysql> show full processlist;

+----+-----------------+-----------------+--------------------+---------+--------+------------------------+-----------------------+
| Id | User            | Host            | db                 | Command | Time   | State                  | Info                  |
+----+-----------------+-----------------+--------------------+---------+--------+------------------------+-----------------------+
|  5 | event_scheduler | localhost       | NULL               | Daemon  | 176845 | Waiting on empty queue | NULL                  |
| 19 | Dotcpp          | localhost:51732 | dotcpp             | Sleep   |  11769 |                        | NULL                  |
| 43 | Dotcpp          | localhost:54206 | information_schema | Query   |      0 | init                   | show full processlist |
| 46 | Dotcpp          | localhost:55737 | dotcpp             | Sleep   |   1137 |                        | NULL                  |
+----+-----------------+-----------------+--------------------+---------+--------+------------------------+-----------------------+
4 rows in set, 1 warning (0.00 sec)
列名解释
IdMySQL服务器为每个客户端连接分配的唯一标识符。这就是之前在innodb_trx里看到的trx_mysql_thread_idKILL命令用的就是这个ID
User建立此连接时使用的MySQL用户名。这里都是Dotcpp,说明来自同一个应用。
Host显示客户端是从哪台机器的哪个端口连接的。格式为hostname:port
localhost:51732:来自本机,操作系统分配的客户端端口是51732。
localhost:54206:另一个连接,端口是54206。
localhost:55737:第三个连接,端口是55737。
db连接当前正在使用的默认数据库。
dotcpp:正在使用dotcpp库。
information_schema:正在查询系统信息。
NULL:未选择数据库。
Command非常重要! 连接当前正在执行的命令类型。
Sleep:连接处于空闲状态,等待客户端发送新命令。通常是事务未结束或连接池中的空闲连接。
Query:连接正在主动执行一个查询
Daemon:MySQL服务器内部的系统守护线程(如事件调度器)。
Time非常重要! 当前状态已经持续的秒数
- 对于Sleep命令,表示连接已经空闲了多久
- 对于Query命令,表示这个查询已经执行了多久
State显示命令执行的详细状态(对于Query命令尤其有用)。Sleep状态的连接通常为空。init表示正在初始化。
Info最关键的一列! 连接正在执行的SQL语句文本。如果为NULL,则表示当前没有在执行SQL。
- 对于Sleep状态的连接,这里显示的是它进入睡眠前最后执行的一条SQL

结合表,我们得知:一个由连接46发起的事务(2432)已经开始了一段时间,它处于“空闲但持有锁”的状态。它自己没有被阻塞,但它手里紧紧抓着3行数据的锁不放,随时可能阻塞其他试图修改这些数据的事务。

点赞(1)

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

Dotcpp在线编译      (登录可减少运行等待时间)