MySQL隐式锁和插入意向锁

发布于:2022-11-28 ⋅ 阅读:(248) ⋅ 点赞:(0)

什么是隐式锁?

当事物需要加锁时,如果这个锁不可能发生冲突,InnoDB会跳过加锁环节,这种机制称为隐式锁。隐式锁时InnoDB实现的延时加锁机制,只有当可能会产生冲突的时候才会加锁,减少锁的数量,提高系统的性能。在Insert过程中不加锁,遇到特殊情况,将隐式锁转为显示锁。

什么是插入意向锁?

插入意向锁时特殊的间隙锁,不同于间隙锁的是,该锁只用于并发操作。尽管属于间隙锁,但是两个事物不能在同一时间一个拥有间隙锁一个拥有插入意向锁(两个有相同的区间)
生成时机:当插入一条新纪录,查看该记录的的下一条记录是否被加上间隙锁,如果已经加上了间隙锁,则Insert被阻塞,并生成一个插入意向锁。
在这里插入图片描述

执行以下语句:

//事务1
begin;
select * from user where id = 16 for update;	//T1时刻
//事务2
begin;
insert into user (id, name, age) values (16, '旭照', 26);	//T2时刻

在这里插入图片描述
可以看到事务产生了(15, 20)区间的间隙锁,当事务2想要插入便会被阻塞,并生成插入意向锁,处于waiting状态。

INSERT如何插入行级锁?

遇到重复的键值

insert into user (id, name, age) values (15, '旭朝', 26);

因为键值重复,以上语句会报错。但是生成错误信息之前,还会局促索引加上S锁:

  • 读提交隔离级别:S型的记录锁,只锁住冲突的记录本身;
  • 可重复读隔离级别:S型的next-key锁;

唯一二级索引重复

无论哪个隔离级别都会对唯一二级索引列加next-key锁。

将age字段设置为唯一二级索引。

 alter table user add unique (age);

插入新的一条字段:

//T1时刻事务1
begin;
insert into user (id, name, age) values (21, '列子', 27);

查看此时数据库表中的锁:只有一个表级别的意向锁
在这里插入图片描述

//T2时刻事务2
begin;
insert into user (id, name, age) values (22, '列子', 27);

在这里插入图片描述
可以看到事务2想要获得S型的next-key锁,但是事务1还没有提交,事务1插入age = 27上面是隐式锁会变为显式锁且类型为X的记录锁,所以事务2处于等待状态。
因此多个事务并发执行,第一个事务插入的记录并不会加锁,而是会用隐式锁保护唯一二级索引。但是当冲突的是普通字段,不是唯一二级索引,两个事物提交后会产生两个一样的数据。为了防止死锁,还是需要尽可能将不能重复的字段设置为唯一索引,保证不会出现重复的数据。

就是这事,散会。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到