前言
什么是间隙锁?
什么时候会使用间隙锁?
间隙锁有什么作用?
操作实战
建表
CREATE TABLE `tb_lock_test` (
`id` bigint(20) DEFAULT NULL,
`a` varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `tb_lock_test`(`id`,`a`) values (1,'a1'),(3,'a3'),(5,'a5'),(7,'a7');
测试无索引下的间隙表情况
开启两个Cmd 模拟两个事务
事务A:
事务B模拟插入
发现阻塞了,事务A commit后 释放间隙锁后,执行成功。
插入一个不是查询范围也发现被锁了说明没有索引的间隙锁会把整个表锁住。
增加普通索引测试
ALTER TABLE tb_lock_test ADD INDEX index_id (id)
有普通索引的不在范围内的不会加锁
下面截图发现 在范围的查询和精确的查询都加了间隙锁。间隙范围就是1-3-5 这个间隙中。1、2 和4 都不可以插入。5以及以后就可以。按照咱们测试场景就是【1,5)符合左闭右开
增加唯一索引测试
ALTER TABLE tb_lock_test ADD UNIQUE index_id (id)
有唯一索引的不在范围内的不会加锁,只会在范围查的时候加锁。从截图可以发现范围查找 符合左开右闭 eg:【1,5)
下面截图发现 在精确的查询只加了行锁。其他范围的都可以插入
增加主键索引测试
ALTER TABLE tb_lock_test ADD PRIMARY KEY(id)
从截图可以发现范围查找 符合左开右闭 eg:【1,5)
下面截图发现 在精确的查询只加了行锁。其他范围的都可以插入和唯一索引一样。
总结
- 不同场景使用间隙锁锁的范围不一样,以及开区间闭区间区别。学会灵活运用。
- 虽然InnoDB中通过间隙锁的方式解决了幻读问题,但是加锁之后一定会影响到并发性能,因此,如果对性能要求较高的业务场景中,可以把隔离级别设置成RC,这个级别中不存在间隙锁。