mysql间隙锁

前面一文 mysql锁 介绍了mysql innodb存储引擎的各类锁,本文介绍一下innodb存储引擎的间隙锁,就如下问题展开讨论mysql

1.什么是间隙锁?间隙锁是怎样产生的?sql

2.间隙锁有什么做用?性能

3.使用间隙锁有什么隐患?spa

1、间隙锁的基本概念

1.什么叫间隙锁

当咱们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但不存在的记录,叫作“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(NEXT-KEY)锁。.net

2.间隙锁的产生

上面的文字很抽象,如今举个栗子,介绍间隙锁是怎么产生的:blog

假设有如下表t_student:(其中id为PK,name为非惟一索引)索引

id name sex address
1 zhaoyi 0 beijin
3 sunsan 1 shanghai
4 lisi 0 guangzhou
5 zhouwu 0 shenzhen
6 wuliu 1 hangzhou

这个时候咱们发出一条这样的加锁sql语句:事务

select id,name from t_student where id > 0 and id < 5 for update;ci

这时候,咱们命中的数据为如下着色部分:get

id name sex address
1 zhaoyi 0 beijin
3 sunsan 1 shanghai
4 lisi 0 guangzhou
5 zhouwu 0 shenzhen
6 wuliu 1 hangzhou

细心的朋友可能就会发现,这里缺乏了条id为2的记录,咱们的重点就在这里。

select ... for update这条语句,是会对数据记录加锁的,这里由于命中了索引,加的是行锁。从数据记录来看,这里排它锁锁住数据是id为一、3和4的这3条数据。

可是,看看前面咱们的介绍——对于键值在条件范围内但不存在的记录,叫作“间隙(GAP)”,InnoDB也会对这个“间隙”加锁。

好了,咱们这里,键值在条件范围可是不存在的记录,就是id为2的记录,这里会对id为2数据加上间隙锁。假设这时候若是有id=2的记录insert进来了,是要等到这个事务结束之后才会执行的

2、间隙锁的做用

总的来讲,有2个做用:防止幻读和防止数据误删/改

1.防止幻读

关于幻读的概念能够参考我这篇文章 https://blog.csdn.net/mweibiao/article/details/80805031 ,这里就很少作解释了

假设有下面场景

时间 事务A 事务B
T1 select count(1) from t_student where id > 1;  
T2   insert into t_student values(2,'qianer',1,'nanjing');
T3   commit;
T4 select count(1) from t_student where id > 1;  
T5 commit;  

若是没有间隙锁,事务A在T1和T4读到的结果是不同的,有了间隙锁,读的就是同样的了

2.防止数据误删/改

这个做用比较重要,假设如下场景:

时间 事务A 事务B
T1 delete from t_student where id < 4;  
T2   insert into t_student values(2,'qianer',1,'nanjing');
T3   commit;
T4 commit;  

这种状况下,若是没有间隙锁,会出现的问题是:id为2的记录,刚加进去,就被删除了,这种状况有时候对业务,是致命性的打击。加了间隙锁以后,因为insert语句要等待事务A执行完以后释放锁,避免了这种状况

三.使用间隙锁的隐患

最大的隐患就是性能问题

前面提到,假设这时候若是有id=2的记录insert进来了,是要等到这个事务结束之后才会执行的,假设是这种场景  

时间 事务A 事务B
T1 select * from t_student where id>1 and id < 100 for update;  
T2   insert into t_student values(2,'qianer',1,'nanjing');
T3 update t_student set xxxx where id=xxx;  
T4 update t_student set xxxx where id=xxx;  
T5 update t_student set xxxx where id=xxx;  
T6  
T7 commit;  

这种状况,对插入的性能就有很大影响了,必须等到事务结束才能进行插入,性能大打折扣

更有甚者,若是间隙锁出现死锁的状况下,会更隐晦,更难定位

相关文章
相关标签/搜索