SQL事务隔离级别之Repeatable Read

109 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第18天,点击查看活动详情

✔个人主页:Mr.Darcy8的掘金主页

🎉欢迎关注👀点赞👍收藏⭐留言📝以及交流人生哲理🎈学习心得🎁

引入

上期我们介绍了第二低的事务隔离级别——Read Committed,一句话概括就是,只会读取已经提交的事务修改的数据,但是可能出现“不可重复读”的错误。

回顾一下“不可重复读”错误是什么:一个重复读取同一个数据的事务A,可能会受并行事务修改该数据的影响而出现读取同一数据不一致的情况。

今天我一起来了解一下比这个事务的隔离级别更高一级的 Repeatable Read

1.幻读

老样子,先说一下这个隔离级别可能遇到的问题。这种隔离级别下的事务可能遇到幻读(Phantom Read) 问题。

顾名思义,应该是读取了不存在的东西,好像遇到幻觉一样。这其实是一个难点,不像前面的几个隔离级别遇到的问题那般简单明了,可能涉及多方面的知识(这也就解释了为啥人们说电话面试的时候会出现幻读的问题)

网上说法也是很多,鱼龙混杂。我们先来看一下mysql给出的官方解释:

The so-called phantom problem occurs within a transaction when the same query produces different sets of rows at different times.

For example, if a [SELECT] is executed twice, but returns a row the second time that was not returned the first time, the row is a “phantom” row.

翻译一下第一段的定义,大致意思是:

所谓的幻影行问题是指,在同一个事务中,同样的查询语句执行多次,得到了不同的行结果集。

这时候有人会说,重复读取出现的问题不是上一个隔离级别Read Committed会出现的问题了吗?怎么现在Repeatable Read还是不能重复读取同一个数据呢?

这里我们就来区分一下不可重复读幻读的区别了。在区别的过程中介绍一下这个神奇的幻读错误。

2.不可重复读与幻读

我们知道,在不可重复读错误中,一个事务重复读取的数据可能被其他事务修改,而事务不会规避这个修改,此时重复查询一个数据的事务就得到了两个不同的结果。

而在幻读错误中,我们强调的是“结果集”的不同,通俗地说是数据量的变化。强调的是“从无到有”。

比如,一个事务A的业务目的是“查询id为1的数据,如果没有则插入一条”,但是其执行完“查询id为1的数据”之后,有别的事务B来插入了一个id为1的数据,那事务A在运行下一步“插入id为1的数据”的时候就会因为主关系键重复而失败。(其实在插入操作当中隐含了一个查询操作,先查询有没有主键冲突,然后sql才会执行真正意义上的插入操作)

代入事务A的视角就是,我明明一开始查过id为1的数据,返回的结果是没有呀?怎么第二次查询(插入操作附带的查询)却又显示有这个数据呢?感觉像是见了鬼一样,不知道是不是自己的幻觉——这样理解“幻读”这个名字不难吧?

所以如果要用一句话简单概括“不可重复读”和“幻读”的区别,大概就是:不可重复读强调数据的内容变化,幻读强调数据集的数量变化(一个是从A到B,一个是从无到有)

新人上路,欢迎互相帮扶~Mr_darcy8的掘金主页

可以的话给咱点个赞呗💖