数据库事务的并发控制是保障数据一致性的核心机制,而脏读(Dirty Read)、不可重复读(Non-repeatable Read)和幻读(Phantom Read)是事务隔离级别设计中需要解决的三大典型问题。理解它们的区别与关联,是掌握事务隔离机制的关键。
一、脏读(Dirty Read):读到未提交的“脏数据”
定义
脏读指一个事务读取到另一个事务未提交的修改数据,若后者发生回滚,前者读取的数据即为无效的“脏数据”。
典型场景:
事务A修改某账户余额为3000元(未提交),事务B此时读取到余额为3000元。若事务A因错误回滚,账户实际余额仍为原值,但事务B已基于脏数据进行了后续操作。
时间顺序 | 事务 A | 事务 B |
1 | 事务开始 | |
2 | 事务开始 | |
3 | 查询此时账户余额 1000 元 | |
4 | 充值 2000 元,使当前余额为 3000 元 | |
5 | 查询此时账户余额为 3000 元(产生脏读) | |
6 | 此时业务异常导致事务回滚,余额变为 1000 元 | |
7 | 消费 1000 元,此时将余额修改为 2000 元 | |
8 | 提交事务 | |
结果 | 正常余额应该为 0 元,但是因产生了脏读,导致事务 B 读取到了事务 A 未提交的数据,因此最后剩余 2000 元 |
如果在时间节点 7 上消费了 3000 元,那岂不是白嫖 2000 元。什么?为什么是 2000 元?你好好想一想
大任浅说~
如同两人同时写一本“正经”小说,A在草稿中加入了 yellow 的场景进行 YY 但未保存。
B直接读取草稿对其他章节也进行了修改,此时因为产生了脏读,导致草稿里加入 yellow 的部分。
A 觉得这样不好,肯定会被抓到小黑屋的,于是最终放弃修改。
B 却不知道 A 还有这癖好,于是看也不看就提交保存了。
结果,悲催了!两人都被抓进了小黑屋
二、不可重复读(Non-repeatable Read):同一数据前后不一致
定义
同一事务内多次读取同一条数据,因其他事务的修改或删除导致结果不一致。
典型场景:
事务A第一次查询用户金额为 3000 元,事务B将余额更新为 1000 元并提交。事务A再次查询时发现金额变为 1000 元,导致逻辑矛盾。
时间顺序 | 事务 A | 事务 B |
1 | 事务开始 | |
2 | 事务开始 | |
3 | 查询此时账户余额 3000 元 | |
4 | 其他操作 | |
5 | 消费 2000 元,使当前余额为 1000 元 | |
6 | 提交事务 | |
7 | 第二次查询账户余额为 1000 元 | |
结果 | 按照逻辑,两次查询的账户余额应该一致。 |
与脏读的区别
- 脏读:读到未提交的数据。
- 不可重复读:读到已提交的修改数据,但事务内结果不一致。
大任浅说~
A 和 B 终于被放出来了
A 猛地一看,妈耶,这小 yellow 书这么多人看。于是连夜准备更新,看着自己的名字在书名下面一阵高兴。于是这次又编辑了一章,突然累了想休息一会,于是就去放飞了一下自己~
可是 B 一看,这么多人看,但是作者不是自己,于是心里不平衡了(凭什么我俩都进小黑屋,最后 A 赚了名气),于是在 A 编辑新章节的时候,改了书名的作者改成自己。
这时 A 放松完小 A 回来,在一看,嗯?作者怎么被改为 B 了?
于是直接顺着网线去找 B,A 和 B 打的昏天黑地的,不一会便被路人举报又抓进小黑屋了。
三、幻读(Phantom Read):数据行“凭空出现”
定义
同一事务内多次按相同条件查询,因其他事务的新增或删除操作导致结果集变化。这个时候事务读取的数据总量和之前统计的不一样,就像产生了幻觉一样,平白无故的多了几条数据,称为幻读。
典型场景:
事务A统计用户表共100条记录,事务B插入10条新记录并提交。事务A再次统计时发现记录数变为110条,如同产生“幻觉”。
时间顺序 | 事务 A | 事务 B |
1 | 事务开始 | |
2 | 事务开始 | |
3 | 查询此时数据量为 100 条 | |
4 | 其他操作 | |
5 | 插入一条数据 | |
6 | 提交事务 | |
7 | 第二次查询,数据总量为 101 条 | |
结果 | 按照正确逻辑,事务A前后两次读取到的数据总量应该一致 |
与不可重复读的区别
- 不可重复读:针对单条数据的修改冲突。
- 幻读:针对结果集范围的新增或删除冲突,表现为行数增减或新行出现
大任浅说~
经过 7 天的思想教育,A 和 B 又一次从小黑屋放出来了。
这次 A 对 B 说:"老 B,这次咱俩分道扬镳吧,我忘了有多少章了,咱回去查一下按照章节数量把稿费分一下吧,一章给你 100 元,够意思吧",B 心想:"你才老 B,反正你也不知道多少章,到时候我在草稿里随便编几章,多赚点"。
等 B 走了,A 拿起手机默默地打开编辑器,一看,嗯,100 章,那就给 B10000 元吧。
此时 B 回到家赶紧用 deepseek 生成十个章节,并且保存。连忙告诉 A,“老 A 啊,你看下 110 章,你就给 11000 就行”,A 一看消息,连忙看了一下编辑器,果然是 110 章,“md,这老 B 敢黑我!”
注:编辑器为事务,章节 or 书名作者为一条数据