在了解MySQL中事务隔离级别的时候,学到这个例子:
为什么事务A第二次select就能查到了,按照mvvc机制来说,不应该还是查不到吗?即使id=5的这一条数据是事务id是A,但是它还是介于m_up_limit_id(事务A的id)和m_low_limit_id(事务B的id加1)之间,所以还是查不到啊,为什么说第二次select就可以查到id=5的这条记录了?
在了解MySQL中事务隔离级别的时候,学到这个例子:
为什么事务A第二次select就能查到了,按照mvvc机制来说,不应该还是查不到吗?即使id=5的这一条数据是事务id是A,但是它还是介于m_up_limit_id(事务A的id)和m_low_limit_id(事务B的id加1)之间,所以还是查不到啊,为什么说第二次select就可以查到id=5的这条记录了?
首先你没有说是什么隔离界别,既然提到了MVCC
那就认为是RR
可重复读。
select
查询,为快照读。update
,此时为当前读。他可以读取到最新的数据,即有id=5的数据存在。由于id为主键且数据存在,只有record lock。小林
如果事务A在最开始使用select .. for update
,那么由于id=5的数据不存在,会加gap lock,这样就会导致后续的事务B执行insert
时阻塞,直到A事务提交完成后,才会继续执行(假如没超时或其他中断的情况下)。
本文参与了SegmentFault 思否面试闯关挑战赛,欢迎正在阅读的你也加入。
你所说的正是mysql默认隔离级别产生幻读现象之一。
事务 A 第一次执行普通的 select
语句时生成了一个 ReadView
,之后事务 B 向表中新插入了一条 id = 5
的记录并提交。接着,事务 A 对 id = 5
这条记录进行了更新操作,在这个时刻,这条新记录的 trx_id
隐藏列的值就变成了事务 A 的事务 id
,之后事务 A 再使用普通 select
语句去查询这条记录时就可以看到这条记录了,于是就发生了幻读。
这个问题的重点在于快照读,快照读可以获取所有 行事务id<=当前事务的id 的行记录,而并不是和它的名字一样产出了所谓的临时表(快照),其他事务改不了。
本文参与了SegmentFault 思否面试闯关挑战赛,欢迎正在阅读的你也加入。
6 回答4.8k 阅读✓ 已解决
2 回答7.4k 阅读✓ 已解决
2 回答6.6k 阅读✓ 已解决
1 回答5.2k 阅读✓ 已解决
1 回答5k 阅读✓ 已解决
3 回答1.9k 阅读✓ 已解决
2 回答1.6k 阅读✓ 已解决
破案了,原来匹配规则还有一条,我看了很多讲mvvc的博客,都漏掉了第一条。我题目中说的情况满足第一条匹配规则,所以能读取到。