概述
本章,您将学习到 MySQL 8 中有关锁机制的知识,内容包括:
- 锁机制的分类
- 演示 InnoDB 存储引擎的行锁
- 演示 InnoDB 存储引擎的表锁
- 锁的查看
- 有关乐观锁、全局锁和死锁的内容
- MVCC
由于内容较多,本文档仅说明锁的查看。
查看事务以及事务的锁
查看当前 MySQL 实例的所有事务:
select * from information_schema.innodb_trx;
查看正在上锁的事务:
# 8.0.13 版本之前的语句
select * from information_schema.innodb_locks;
# 8.0.13 以及 8.0.13 版本之后
select * from performance_schema.data_locks;
查看等待锁的事务:
# 8.0.13 版本之前
select * from information_schema.innodb_lock_waits;
# 8.0.13 以及 8.0.13 版本之后
select * from performance_schema.data_lock_waits;
输出信息说明
use locks;
set autocommit=0;
start transaction;
select * from information_schema.innodb_trx\G;
*************************** 1. row ***************************
trx_id: 421393993788632
trx_state: RUNNING
trx_started: 2025-12-15 20:01:42
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 0
trx_mysql_thread_id: 23
trx_query: select * from information_schema.innodb_trx
trx_operation_state: NULL
trx_tables_in_use: 0
trx_tables_locked: 0
trx_lock_structs: 0
trx_lock_memory_bytes: 1128
trx_rows_locked: 0
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)
rollback;
\G 表示将输出的各列以单行方式进行垂直展现:
- trx_id - 事务的唯一 ID 号
- trx_state - 事务的执行状态,允许的状态值有 RUNNING、LOCK WAIT、ROLLING BACK、COMMITTING
- trx_started - 事务开始的时间
- trx_requested_lock_id - 事务当前正在等待的锁 ID 号,如果 trx_state 为 LOCK WAIT,则此处为具体的锁 ID 号;否则为 NULL
- trx_wait_started - 事务开始等待的锁的时间
- trx_weight - 事务的权重,反映的是更改的行数与锁定的行数(不一定是确切的数)。在 InnoDB 中,如果发生死锁需要回滚,那么 InnoDB 会选择最小的值进行回滚
- trx_mysql_thread_id - 事务的线程 ID
- trx_query - 事务正在执行的 SQL 语句
- trx_operation_state - 事务的当前操作状态,没有则为 NULL
- trx_tables_in_use - 当前事务使用 innodb 存储引擎的表的个数
- trx_tables_locked - 当前 SQL 语句具有行锁的 innodb 表数(因为这些是行锁而不是表锁,所以表通常仍然可以被多个事务读取和写入,尽管有些行是锁定的)
- trx_lock_structs - 当前事务持有的锁结构数量。它反映了事务锁的复杂程度,值越高表示事务持有更复杂的锁结构。每个锁(无论是行级锁还是表级锁)都会占用一个锁结构。
- trx_lock_memory_bytes - 此事务的锁结构在内存中占用的总大小,单位为字节(byte)
- trx_rows_locked - 此事务锁定的大致行数,该值可能包括实际存在但对事务不可见的已删除标记行
- trx_rows_modified - 此事务中修改与插入的行数
- trx_concurrency_tickets - 事务当前持有的并发度票数量(每个事务在 InnoDB 中持有一个并发度票(ticket)),与系统变量 innodb_concurrency_tickes 的值关联
- trx_isolation_level - 当前事务的隔离级别
- trx_unique_checks - 是否为当前事务打开或关闭唯一性检查
- trx_foreign_key_checks - 是否为当前事务打开或关闭外键检查
- trx_last_foreign_key_error - 最后一个外键的详细错误信息,没有则为 NULL
- trx_adaptive_hash_latched - 监控事务对自适应哈希索引(Adaptive Hash Index,AHI)的锁定状态。当事务当前正在访问或修改 AHI,trx_adaptive_hash_latched 字段的值为 YES(1),否则为 NO(0)
- trx_adaptive_hash_timeout - 监控事务对自适应哈希索引(AHI)的锁定超时状态
- trx_is_read_only - 事务是否是只读
- trx_autocommit_non_locking - 标识事务是否使用了非锁定自动提交(autocommit non-locking)模式。非锁定自动提交(autocommit non-locking)是 MySQL 中一种优化读操作的事务模式。值为 1,表示是一个没有使用 for update 或 lock in share mode 的 select 语句,且开启了 autocommit 。若此字段与 trx_is_read_only 同时为 1,InnoDB 会对此事务进行优化,以降低事务修改表数据时的开销。
- trx_schedule_weight - 冲突感知事务调度(Contention-Aware Transaction Scheduling ,CATS)算法为锁等待事务分配的调度权重值。当多个事务在等待同一个对象上的锁时,CATS 算法确定哪个事务首先接收锁。值越大,优先级越高。在 8.0.20 之前的版本,使用的是先进先出(FIFO)算法来调度事务;从 8.0.20 以及之后的版本使用 CATS 算法。
use locks;
set autocommit=0;
start transaction;
# 加一个记录锁(排他锁,行锁)。此时 InnoDB 存储引擎会自动添加一个 IX 锁
seletc * from tlock1 where id=1 for update;
select * from performance_schema.data_locks\G;
*************************** 1. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 139919017077976:110:1140:139919028704224
ENGINE_TRANSACTION_ID: 30244
THREAD_ID: 57
EVENT_ID: 264
OBJECT_SCHEMA: locks
OBJECT_NAME: tlock1
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: NULL
OBJECT_INSTANCE_BEGIN: 139919028704224
LOCK_TYPE: TABLE
LOCK_MODE: IX
LOCK_STATUS: GRANTED
LOCK_DATA: NULL
*************************** 2. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 139919017077976:110:78:4:2:139919028701232
ENGINE_TRANSACTION_ID: 30244
THREAD_ID: 57
EVENT_ID: 264
OBJECT_SCHEMA: locks
OBJECT_NAME: tlock1
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: PRIMARY
OBJECT_INSTANCE_BEGIN: 139919028701232
LOCK_TYPE: RECORD
LOCK_MODE: X,REC_NOT_GAP
LOCK_STATUS: GRANTED
LOCK_DATA: 1
2 rows in set (0.00 sec)
rollback;
- ENGINE - 持有或请求锁的存储引擎
- ENGINE_LOCK_ID - 存储引擎持有或请求的锁 ID
- ENGINE_TRANSACTION_ID - 请求锁的事务 ID
- THREAD_ID - 持有锁的线程 ID
- EVENT_ID - 事件(Event)的 ID。事件(event)由一组 SQL 语句集合组成,主要的作用是周期性运行数据库对象,用来实现 MySQL 的计划任务。
- OBJECT_SCHEMA - 库名称
- OBJECT_NAME - 表名称
- PARTITION_NAME - 锁的分区名称
- SUBPARTITION_NAME - 锁的子分区名称
- INDEX_NAME - 锁的索引名
- OBJECT_INSTANCE_BEGIN - 内存中锁的起始地址
- LOCK_TYPE - 锁的类型。取决于存储引擎,对于 InnoDB,值可以有 RECORD、TABLE
- LOCK_MODE - 请求锁的方式
- LOCK_STATUS - 锁请求的状态。取决于存储引擎,对于 InnoDB,值可以有 GRANTED (锁被持有)和 WAITING (锁正在等待)。
- LOCK_DATA - 与锁关联的数据(如果有的话)
也可以使用 show open tables from 库名; 来查看:
show open tables from locks;
+----------+---------+--------+-------------+
| Database | Table | In_use | Name_locked |
+----------+---------+--------+-------------+
| locks | t1 | 0 | 0 |
| locks | tindex1 | 0 | 0 |
| locks | tb1 | 0 | 0 |
| locks | tlock1 | 0 | 0 |
+----------+---------+--------+-------------+
4 rows in set (0.00 sec)
- Database - 库名
- Table - 表名
- In_use - 该表的表锁或锁请求数,如果为 0 表示表已经打开但当前未使用。如果一个连接会话使用了表锁(
lock table 表名 write;) 则 In_use 将为 1 - Name_locked - 表名是否被锁。主要用于对表进行删除或重命名等操作。
版权声明:「自由转载-保持署名-非商业性使用-禁止演绎 3.0 国际」(CC BY-NC-ND 3.0)
用一杯咖啡支持我们,我们的每一篇[文档]都经过实际操作和精心打磨,而不是简单地从网上复制粘贴。期间投入了大量心血,只为能够真正帮助到您。
暂无评论










