开发者社区> 问答> 正文

GAP锁为什么要锁住索引间的区间,而不是直接锁住值相等的就行了? 400 报错

GAP锁为什么要锁住索引间的区间,而不是直接锁住值相等的就行了? 400 报错

如:

+-----+--------+---------+
| id      | userId | name    |
+-----+--------+---------+
| 100 | 100010 | ce1     |
| 200 | 100020 | 1232131 |
| 300 | 100030 | ce3     |
| 400 | 100040 | ce4     |
+-----+--------+---------+

 

id是PK,  userId是普通非唯一索引

 

A事务:

begin;

update user set name ='tt' where userId='100030';

 

 

B事务:

insert into user (userId,name) values('100021','tttt');

因GAP锁插入阻塞

 

 

问题:为啥mysql是不直接阻塞插入100030的记录,而要阻塞间隙锁100020-100030, 100030-100040。

 

展开
收起
爱吃鱼的程序员 2020-05-30 22:27:23 729 0
1 条回答
写回答
取消 提交回答
  • https://developer.aliyun.com/profile/5yerqm5bn5yqg?spm=a2c6h.12873639.0.0.6eae304abcjaIB

    innodb在rr级别上的gap锁是为了解决幻读的问题

    你说的相等值,其实就是rc级别的行级锁,只能避免不可重复读

    ######回复 @bboo : 嗯, 理解,确实是,谢了!######回复 @爱吃大肉包 : 我的意思是对于你这100030这数据的话,锁住一行就可以了.但是显然,只锁住一行是解决不了幻读的问题的,就如我刚才举的例子,删除一个不存在的索引举无法锁住一行.间隙锁是在性能和并发之间做一个取舍######回复 @bboo : 不知道我理解是否有问题,我理解的插入引起的幻读就是 update user set name ='tt' where userId='100030';影响行数就是1行,第二次2行。 如果改成select ...for update, 就是每次查出的记录都是一样的。 所以我才得出,只要锁住单条记录就行了。 你列举的 '8888888' 好像并没影响我的执行结果######回复 @bboo : 索引直接不存在,更不用谈加锁了,解决幻读只能通过间隙锁住 100040-正无穷 来控制8888888这个索引字段的插入. 而rc级别下就会通过行锁保证可重复读 innodb通过这些配置实际上隔离级别高了一个标准######回复 @爱吃大肉包 : 你考虑下删除的情况,比如你删除88888888的时候,这条数据不存在.
    2020-05-30 22:27:23
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载