修改
了这条记录的同个字段 , 接着 Session A 再重复上一次查询 , 两次结果不同了
, 这就发生了不可重复读 。
不可重复读示意图
发生时间编号Session ASession B①BEGIN;
②SELECR * FROM student WHERE no = 1; (此时读出来是小明
)
③
BEGIN;UPDATE student SET name = '李四' WHERE no = 1;COMMIT;④SELECR * FROM student WHERE no = 1; (读出来是李四
, 跟上次不同 , 则发生了不可重复读)
⑤
BEGIN;UPDATE student SET name = '王五' WHERE no = 1;COMMIT;⑥SELECR * FROM student WHERE no = 1; (读出来是王五
, 又跟上次不同 , 则发生了不可重复读)
已知表中仅有一条no为1、name为小明
的记录 。
Session A 第一次查询该记录为小明
(注意还没有COMMIT) , 接着 Session B 修改该记录为李四
, 然后 Session A 再次查询发现变成李四
了 , 跟上一次查询结果不同 , 这种现象称为不可重复读
。同理 Session B 又修改值为王五
, 紧接着Session A 又再次查询发现结果又变了 , 变成了王五
, 因为发生了不可重复读
。
对于这种现象 , 在现实中很多场景下中我们会认为这是合理的、可以接受的 , 每次查询就应该查出当前最新的数据 , 但处于并发事务内的角度来看这属于一种问题 。
4. 幻读(Phantom Read)对于两个事务 Session A、Session B , Session A 读取了一条记录的一个字段 , 然后 Session B 往表插入
一些新的记录 , 之后 Session A 再次读取
发现多出了新的记录 , 这就算幻读 。
幻读示意图
发生时间编号Session ASession B①BEGIN;
②SELECR * FROM student WHERE no > 0; (此时读出来只有小明
一条记录)
③
BEGIN;INSERT INTO student VALUES(2, '李四', 19);COMMIT;④SELECR * FROM student WHERE no > 0; (此时读出来有小明
、李四
两条记录 , 发生了幻读)
已知表中仅有一条no为1、name为小明
的记录 。
Session A 第一次查询限定条件为 no > 0
, 查出来一条记录为小明
(注意还没有COMMIT) , 接着 Session B 插入了一条记录李四
, 然后 Session A 再次查询结果为小明
、李四
两条记录了 , 多了一条 , 这种现象称为幻读
, 而多出来的记录称为幻影记录
。
对于这种现象 , 还是那句话 , 在现实中很多场景下中我们会认为这是合理的、可以接受的 , 但处于并发事务内的角度来看这属于一种问题 。
对于幻读的注意点:
幻读强调的是多出来的
记录 。按照示意图 , 如果 Session B 不是插入记录 , 而是删除记录 , 那 Session A 再次查询发现记录数量变少了 , 这种现象不属于幻读 。由于第二次查变少了 , 严格归类的话 , 这种现象属于不可重复读
。
5.3 SQL标准的四种隔离级别按照并发问题严重程度高到低排序:脏写
> 脏读
> 不可重复读
> 幻读
由于脏写
问题是无法接受的 , 所以现在市面主流数据库都不会出现这个问题 , 那还剩下后面3个问题 。如果能把所有问题都解决那肯定最好 , 但也就意味着并发性能最差 , 如果要最高的并发性能 , 又会出现数据并发的问题......因此回到前面说的权衡取舍问题了 , 看不同的场景是要
经验总结扩展阅读
- 如何打开电脑的屏幕键盘
- 四个字成语和峡有关的
- 我的 Kafka 旅程 - Producer
- Windows esp-idf 安装
- 建议收藏 Java线程同步的四种方式详解
- 历史上武则天和狄仁杰的关系
- 下 MySQL数据库-数据表
- 2023年10月21日是补墙的黄道吉日吗 2023年10月21日补墙好吗
- 乔丹的招牌动作有哪些
- 包贝尔的电影有哪些