SQL的事务( 三 )

,则发生了脏读)
⑤COMMIT;

ROLLBACK;已知表中仅有一条no为1、name为小明的记录 。
Session A 与 Session B 各自开启自己的事务,Session B 的事务先将no为1的记录修改name列的值为李四 , 然后紧接着 Session A 查询这条记录,如果发现读到的数据为李四,即读到了Session B 中还没有提交的数据,之后 Session B 进行了回滚,数据还原回小明 , 那么 Session A 读到的李四就是一个不存在的数据,这种现象称为脏读
在某些场合下,返回不存在的数据、假的数据给客户,是可能会出大问题的 。
3. 不可重复度(Non-Repeatable Read)对于两个事务 Session A、Session B,Session A 读取了一条记录的一个字段 , 然后 Session B 修改了这条记录的同个字段,接着 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个问题 。如果能把所有问题都解决那肯定最好 , 但也就意味着并发性能最差,如果要最高的并发性能,又会出现数据并发的问题......因此回到前面说的权衡取舍问题了,看不同的场景是要数据绝对准确性,还是要最高的并发性能 , 亦或牺牲部分并发性能以换取数据的相对准确

推荐阅读