数据库事务隔离级别:
不同隔离级别引发的问题:
对于同时运行的多个事务(多线程并发), 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题: (问题的本质就是线程安全问题,共享数据的问题)
1. 脏读
: 对于两个事务 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚, T1读取的内容就是临时且无效的.
1. 不可重复读
: 对于两个事务 T1, T2, T1 读取了一个字段, 然后 T2 更新并提交了该字段. 之后, T1再次读取同一个字段, 值就不同了.
1. 幻读
: 对于两个事务 T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入、删除了一些新的行. 之后, 如果 T1 再次读取同一个表, 就会多出、少了几行.
1,幻读: 说的是存不存在的问题:原来不存在的,现在存在了,则是幻读 ( 对应:Insert 、Delete )
2,不可重复读: 说的是变没变化的问题:原来是A,现在却变为了B,则为不可重复读( 对应:Update )
从数据库实现上去理解:幻读是表锁,不可重复读是行锁
**可重复读隔离级别(Repeatable Read Isolation Level)**
一、可重复读(Repeatable Read)的概念
可重复读取隔离级别 只能看到(当前)事务开始之前提交的数据;它从不看到未提交的数据或并发事务在(当前)事务执行期间提交的更改。
二、Read Committed 隔离级别下的【不可重复读】发生场景举例
1、小明很开心自己考了69分,于是他连接到数据库查询自己的成绩来炫耀给小伙伴。
2、
1)接着小明觉得还不尽兴,于是又查一次。
2)不幸的是,小明的班主任王老师复查试卷后,发现小明的成绩多加了10分,于是他连接到数据库来修改小明的成绩到 59分,王老师为了继续检查,并未提交事务。
3)那么,小明的第二次查询结果还是69分。他不知道自己其实是不及格的。除非等到王老师的更新操作提交(commit)以后,他再进行一次查询。
4)此时同一事务中,小明的第三次查询结果与第二次查询结果不一致,即为:不可重复读
说明:如果小明已经读到数据,但是当前事务未结束,在 Repeatable Read 隔离级别下,王老师是获取不到对数据的修改权限的。因为已经被小明读到了。Repeatable Read 会保证这两次读取到的数据是一样的,意味着对读取到的数据限制其它事务对其修改。
但是在 Read Committed 隔离模式下,小明的事务允许王老师的事务对其读取到的数据进行修改,这样就导致了同一事务中读取的数据不一致(不可重复度)。
三、读已提交 vs 可重复读 vs 序列化
【读已提交】:是一种隔离级别,可确保读取当前已提交的任何数据。 它只是限制读者看到任何中间的、未提交的、“脏”的阅读。 它不承诺如果事务重新发出读取,将找到相同的数据,数据在读取后可以自由更改。
【可重复读】:是更高的隔离级别,即除了保证【读已提交】级别之外,还保证读到的任何数据都不能被改变,即:如果事务再次读到同样的数据,就会发现之前读到的数据在原地,不变 ,并且可以阅读。
【序列化】:提供了更强大的保证:除了所有可重复读取保证之外,它还保证后续读取不会看到新数据。