欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > 【mysql】锁机制 - 4.插入意向锁

【mysql】锁机制 - 4.插入意向锁

2025/6/27 23:26:19 来源:https://blog.csdn.net/lixiaonan0318/article/details/143859355  浏览:    关键词:【mysql】锁机制 - 4.插入意向锁

插入意向锁(Insert Intension Lock)

是实际在插入操作前,提出一个插入的意向,检查其所属的范围是否存在间隙锁。

注意,插入意向锁虽然叫做意向锁,但其本质上是一种间隙锁,因为意向锁是表锁,而插入意向锁是行锁。

MySql 手册 中对插入意向锁的解释:

插入意向锁是在插入一条记录行前,由 INSERT 操作产生的一种间隙锁。该锁用以表示插入意向,当多个事务在同一区间(gap)插入位置不同的多条数据时,事务之间不需要互相等待。假设存在两条值分别为 4 和 7 的记录,两个不同的事务分别试图插入值为 5 和 6 的两条记录,每个事务在获取插入行上独占的(排他)锁前,都会获取(4,7)之间的间隙锁,但是因为数据行之间并不冲突,所以两个事务之间并不会产生冲突(阻塞等待)。

插入意向锁的特点

  • 是一种特殊的间隙锁,用于锁定两个记录之间的间隙

  • 插入意向锁之间互不排斥,可以共存

  • 插入意向锁与间隙锁是互斥的,不能共存

那么问题来了:既然有了间隙锁,为什么还需要插入意向锁?

  • 间隙锁是为了防止其他事务的插入,为了防止幻读而设计的;插入意向锁是为了优化并发插入效率而设计的

  • 间隙锁之间可以共存,即:两个事务在同一时间可以拥有同一个间隙的间隙锁(因为间隙锁本质是为了防止插入)

  • 插入意向锁和间隙锁不能共存,即:两个事务不能在同一时间内,一个拥有间隙锁,另一个拥有该间隙的插入意向锁

  • 插入意向锁是配合着间隙锁使用的,二者相互配合才能实现可重复读

比如我们创建如下表结构:

CREATE TABLE IF NOT EXISTS `test1` (`id`   INT PRIMARY KEY,`name` VARCHAR(100)
);
INSERT INTO test1 (id, name) VALUES (15, 'A'), (20, 'B'), (30, 'C');

id

name

15

A

20

B

30

C

开启以下2个事务:

事务1

事务2

Begin;

Begin;

Time1

UPDATE test1 SET name = 'D' WHERE id = 25;

获得IX锁和20-30记录的间隙X锁

Time2

UPDATE test1 SET name = 'E' WHERE id = 26;

获得IX锁和20-30记录的间隙X锁

Time3

INSERT INTO test1 (id, name) VALUES (25, 'D');

等待20-30记录的插入意向锁

Time4

INSERT INTO test1 (id, name) VALUES (26, 'E');

等待20-30记录的插入意向锁

  • TIme1:事务1获得了意向排他锁和 (20, 30) 范围的间隙锁

  • Time2:事务2获得了意向排他锁和 (20, 30) 范围的间隙锁(意向锁和意向锁之间不会冲突,间隙锁和间隙锁之间也不会冲突)

  • TIme3:INSERT 操作尝试获得 (20, 30) 范围的插入意向锁,但被事务2的间隙锁阻塞

  • TIme4:INSERT 操作尝试获得 (20, 30) 范围的插入意向锁,但被事务1的间隙锁阻塞

因此循环等待造成了死锁。

可以查看 INNODB 死锁日志:

SHOW ENGINE INNODB STATUS;

输入日志内容:

...
------------------------
LATEST DETECTED DEADLOCK
------------------------
2024-11-21 15:24:06 0x16da9b000
*** (1) TRANSACTION:
TRANSACTION 2180072, ACTIVE 14 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1128, 2 row lock(s)
MySQL thread id 3296, OS thread handle 6156677120, query id 174792 localhost 127.0.0.1 root update
INSERT INTO test1 (id, name) VALUES (25, 'D')*** (1) HOLDS THE LOCK(S):
RECORD LOCKS space id 508 page no 4 n bits 72 index PRIMARY of table `db-test`.`test1` trx id 2180072 lock_mode X locks gap before rec
Record lock, heap no 4 PHYSICAL RECORD: n_fields 4; compact format; info bits 00: len 4; hex 8000001e; asc     ;;1: len 6; hex 0000002143e2; asc    !C ;;2: len 7; hex 820000016d012a; asc     m *;;3: len 1; hex 43; asc C;;*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 508 page no 4 n bits 72 index PRIMARY of table `db-test`.`test1` trx id 2180072 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 4; compact format; info bits 00: len 4; hex 8000001e; asc     ;;1: len 6; hex 0000002143e2; asc    !C ;;2: len 7; hex 820000016d012a; asc     m *;;3: len 1; hex 43; asc C;;*** (2) TRANSACTION:
TRANSACTION 2180073, ACTIVE 8 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1128, 2 row lock(s)
MySQL thread id 17733, OS thread handle 6154448896, query id 174796 localhost 127.0.0.1 root update
INSERT INTO test1 (id, name) VALUES (26, 'E')*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 508 page no 4 n bits 72 index PRIMARY of table `db-test`.`test1` trx id 2180073 lock_mode X locks gap before rec
Record lock, heap no 4 PHYSICAL RECORD: n_fields 4; compact format; info bits 00: len 4; hex 8000001e; asc     ;;1: len 6; hex 0000002143e2; asc    !C ;;2: len 7; hex 820000016d012a; asc     m *;;3: len 1; hex 43; asc C;;*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 508 page no 4 n bits 72 index PRIMARY of table `db-test`.`test1` trx id 2180073 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 4; compact format; info bits 00: len 4; hex 8000001e; asc     ;;1: len 6; hex 0000002143e2; asc    !C ;;2: len 7; hex 820000016d012a; asc     m *;;3: len 1; hex 43; asc C;;*** WE ROLL BACK TRANSACTION (2)
...

参考:

MySQL :: MySQL 8.0 Reference Manual :: 17.7.1 InnoDB Locking

字节面试:加了什么锁,导致死锁的? | 小林coding

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词