本地环境,MySQL的版本是5.7.16 ;数据库的隔离级别是Repeatable Read(可重读)
MySQL5.5 开始,InnoDB成为MySQL的默认存储引擎。今天主要介绍InnoDB的各种锁机制。
1、InnoDB行锁算法-记录锁(Record Lock)
- 锁住单行记录
2、InnoDB行锁算法-间隙锁(Gap Lock)
- 间隙锁的说明: 间隙锁在InnoDB的唯一作用就是防止其它事务的插入操作,以此来达到防止幻读的发生,所以间隙锁不分什么共享锁与排它锁
- 下面是我的测试数据emp表,id是自增主键,name是varchar,age、scores都是int。
-
首先我们开启一个事务读取id大于3的记录
BEGIN;
select * from emp where id > 3 for update;
//for update 对于有索引的列是行锁
返回结果如下,此时我们不提交也不回滚这个查询事务,这个时候InnoDB会生成间隙锁,锁住指定查询条件的下一个区间,即所有大于3的记录。
开启另一个事务,做插入的操作,此时这个事务会一直等待,因为我们刚刚查询的事务没有提交,而现在我们插入的记录Id是8,而这个区间已经被间隙锁给锁住了。我们上面说了间隙锁的目的是防止幻读,
因为如果这次插入成功了,那么此时如果另一个事务也执行查询id>3的SQL返回的结果会比上一个事务读取的记录数多。这就导致两个相同的查询语句读取到的记录不一致,也就是产生了幻读。
所以下面这个sql语句会堵塞,等待锁。
BEGIN;
insert into emp(name,age,scores) VALUES(8,'小蓝',28,87);
3、InnoDB默认
行锁算法-临键锁(Gap Lock)
临键锁=记录锁+间隙锁,是MySQL InnoDB存储引擎默认的行锁算法。
Next-Key Lock锁到底作用:
当查询的索引是唯一索引或主键时,InnoDB会对Next-Key Lock进行优化,将其降级为Record Lock,即仅锁住索引本身,而不是范围。当查询的索引为辅助索引时,InnoDB则会使用Next-Key Lock进行加锁。InnoDB对于辅助索引有特殊的处理,不仅会锁住辅助索引值所在的范围,还会将其下一键值加上Gap LOCK。