开发者社区 问答 正文

阿里二面之MVCC能不能解决幻读?:报错

不想看逼逼直接跳到最后,还能请各位大佬赐教,这个问题真的是总所纷纭。

一上来很严肃,看起来心情不是很好,然后问了我第一个问题,mysql如何解决幻读?
我首先说的是间隙锁(应该是next-key),但是这方面的思想我忘了,他就追问我具体如何解决的,解决办法如下:(当时没能答出来)
【锁算法】
record:记录锁,单行记录加锁

gap:间隙锁,锁住一个范围

next-key:等于record+gap两者结合

【场景解释】

背景:表:tab,主键=id,索引=user_id

当发生update tab set age = 10 where user_id>10;时候,加锁如下:

1.主键索引id会给id=10的记录加上record行锁

2.索引user_id上会加上gap锁,锁住user_id (10,+无穷大)这个范围

所以,在插入 user_id =100的记录时候会命中第二个索引上加的锁会报出事务异常;

所以在事务中即使查询多次user_id>10的返回结果都是一样的,因为期间内的数据都没有变化,这样就解决了幻读的问题;
然后我集中生智说了另外一种办法:mvcc
他的语气怎么说?更沉重了!吓得我都不敢大声说话了。然后给他解释了如何MVCC如何解决幻读,最后终于解释清楚了,他说MVCC这种看起来像解决了幻读,但是实际应该有什么小问题,数据应该还是插入到了这个事务得结果集里面,然后说这种方法是掩耳盗铃,其实没有解决。。。。。。。,还说MVCC这种东西在实际开发中没用。
最后实在没法我又补充了一句表锁,他说这不是废话,这是最简单得方法。
后面就是快乐得一起偏僻,其实这个面试官真的不是很严肃。
后来我查了资料,有人说可以,有人说不行。

所以说各位大佬!!!!MVCC到底能不能解决幻读???????

这个帖子我是发在牛客上的,也收集了一些资料。后面是几种说法:

1.能解决,使用MVCC,在第一次读取的时候就产生了快照,你再读取还是历史数据(即快照数据),其余事务插入或者删除数据不会影响。

2. 只解决了部分,只解决了读的问题。没有解决update问题。 并且推荐我去看这个帖子 https://www.cnblogs.com/liyus/p/10556563.html

3.不能解决,我查阅了MYSQL的官方文档,发现关于幻读解决办法只有用Next-key

4. 幻读分为两种,一种是当前读,这种需要Next-key解决,一种是快照读,快照读可以使用MVCC解决的。

5.为什么MySQL在可重复读隔离级别下可以解决幻读?
答:因为使用了间隙锁;(这个位置我感觉有错误,可重复度的隔离级别是不能解决幻读的)
首先,要理解,只有在当前读的前提下才会出现幻读,快照读是不存在幻读的,我每一次快照读都是一致的.所以,既然都是当前读了,MVCC当然不可以解决幻读,因为当前读,读取的是最新的数据.

最后提出一个问题? 想问一下,主键id加record锁作用是啥啊,直接加间隙锁可以吗?

展开
收起
kun坤 2020-06-08 11:05:39 1065 分享 版权
1 条回答
写回答
取消 提交回答
  • 个人见解,MVCC多版本并发控制,不能解决幻读。

    幻读, 默认的事务隔离级别是REPEATABLE READ。采用Next-Key Locking的算法。

    Next-Key Locking( Record Lock + Gap Lock ) 锁定一个范围,并且锁定记录本身 。

    主键Id加record锁,是锁定记录本身,如果解决幻读不能直接加 Gap Lock

     

    ######可重复度的事务隔离级别好像不能解决幻读吧,但是next-key确实可以解决幻读。######

    有意思 到底能不能啊

    ######我也不知道,这个问题提出来后,总说纷纭,我还去stackoverflow上提问了,也没人回答,然后只好去看看了看官方文档,官方文档关于幻读得解决只提到了next-key。应该没有解决的吧。
    2020-06-08 15:04:06
    赞同 展开评论
问答分类:
问答地址: