mysql 间隙锁(GAP-LOCK)演示

1.演示说明

       间隙锁主要是为了解决RR级别下的幻读(当前读)快照读的情况下通过mvcc(版本并发控制)就可以解决。

        mysql版本 8.0.13(mysql8版本自带的data_lock可以更直观的看到加锁信息)事务隔离级别为RR(默认不用修改)

      如果是5.7版本的需要通过show variable like 'innodb_locks_unsafe_for_binlog';查看间隙锁是否开启,如果没有可以在mysql配置文件添加innodb_locks_unsafe_for_binlog=0;(否则间隙锁不生效)  

2.表和数据准备

        

create table test.user
(
    id    bigint auto_increment
        primary key,
    name  varchar(50) null,
    money int(20)     null
);

create index index_money
    on test.user (money);

insert into user  values(1,'a',10),

insert into user  values(4,'b',30);

insert into user  values(10,'c',9);

创建了一张user表 里面就三个字段其中id为主键唯一索引 money为普通索引字段(间隙锁锁的是索引位置间隙的范围)

3.测试

 普通索引

目前变种存在的区间(无穷小,9)(9,10) (10,30) (30,无穷大)

 测试的案例都是在两个事务中进行的

 案例1;

   

事务1事务2
begin ;
select  *  from  user where money=10 for update ;
begin ;
set innodb_lock_wait_timeout =5;
insert into user values (null,'a',9);(阻塞)
insert into user values (null,'a',10);(阻塞)
insert into  user values (null,'a',29);(阻塞)insert into user values (null,'a',30);(成功)
delete  from  user where money=30;(成功)
delete  from  user where money=30;(成功)

delete from user where money=10;(阻塞)

 

      事务1语句锁的区间为(9,10)(10,30)

 查看data_lock表中的信息

在表中可以看到  有四条数据 第一条 意向锁  第3条 行锁  二和四  为间隙锁 

看官网说间隙锁是 左开右闭,我测试结果只有使用范围的时候才会出现对于等值查询 结果是相反的      

   

案例2

事务1事务2
begin ;
select  *  from  user where money>10 for update ;
begin ;
set innodb_lock_wait_timeout =5;
insert into user values (null,'a',9);(成功)
insert into user values (null,'a',30);(阻塞)
insert into  user values (null,'a',40);(阻塞)
delete  from  user where money=30(阻塞)
delete  from  user where money=10;(成功)

事务1中的语句锁的区间相当于是(10,无穷大)

锁信息

 

 

主键索引

对于主键索引如果采用等值查询 并加锁,并不会产生间隙锁,只会生成行锁(记录锁)

案例一

等值查询

     

事务1事务2
begin ;
select * from user where id=4   for update ;
insert into  user values  (5,'a',30);(成功)

锁信息

 

案例2

范围查询

begin ;
select * from user where id>4   for update ;
insert into  user values  (5,'a',30);(阻塞)
insert into  user values  (null,'a',30);(阻塞)
insert into  user values  (3,'a',30);(成功)

     对于id>4 锁的同样是相当于(4,无穷大)

   锁信息

   

其它的案例就不在一一列举,有兴趣的自己可以测试一下,另外有很多公司innodb的隔离级别都改成了RC,既然RR可以通过间隙,临键锁解决幻读为什么不用反而要更改成RC?    有兴趣的同学可以在评论区留言,包括半一直读

     

         

     

     


版权声明:本文为weixin_41638098原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。