SQL的事务( 四 )

修改了这条记录的同个字段 , 接着 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个问题 。如果能把所有问题都解决那肯定最好 , 但也就意味着并发性能最差 , 如果要最高的并发性能 , 又会出现数据并发的问题......因此回到前面说的权衡取舍问题了 , 看不同的场景是要

经验总结扩展阅读