数据库事务,ACID四个特性大家都知道,本次主要是记录自己学习 事务隔离性时,事务隔离级别以及所能解决 并发带来的问题。
在多个事务【并发操作】相同的表数据时,为了让多个事务都可以得到正确的结果,不会因为互相的交叉操作产生干扰,同时还要保证一定的执行效率,故而提出了不同的隔离级别。
一、常见的并发异常
读取到了脏数据:指的是一个事务读取到了,其他事务未提交的数据,未提交意味着这些数据可能会回滚,读到的数据不一定准确。
不可重复读:官方解释,事务A 修改了 另一个未提交的事务 (事务B)读取过的数据。那么B事务再次读取 ,会发现两次读取的事务不一致。也就是说在一个原子性的操作中,一个事务两次读取的数据不一致。主要是update语句, 会导致不可重复读。
幻读:一个事务按照某些条件进行查询,事务提交前,有另一个事务插入了满足条件的其他数据,再次使用相同条件查询,却发现多了一些数据,就像出现了幻觉一样。幻读主要针对,delete和insert语句。
事务隔离级别:RU、RC、RR、Serializable
二、事务隔离级别以及解决的问题()
RU:读未提交,[RU隔离级别,就是一个事务 可以读取其它 [未提交事务] 修改的数据,这种隔离级别最低,该隔离级别下 各种问题都会产生,看上面的时刻图,可以容易理解,为什么它解决不了某些问题。
实现原理:根本不需要加锁,可以理解为没有隔离。
RC:读已提交, 指当前事务只能读取到其他事务已经提交的数据, 该隔离级别可能产生 不可重复读 和幻读问题。
(在数据库中,读操作(select操作),是可以多个事务 同时执行的,即在多处理器的环境中,多个事务同时对 同一个数据进行读取。)
(说明解决,脏读问题,根据字面意思也能理解, 当前事务只能读取到其他事务 已经提交的数据,自然不会读取到其他事务未提交的数据,自然不会发生脏读问题。)
实现原理:比较复杂(学了MVCC再写吧)(既要满足一定的并发性,又要解决一些问题)
MySQL事务隔离级别和实现原理(看这一篇文章就够了!) - 知乎 (zhihu.com)
RC事务隔离级别能够解决,第一类丢失更新问题, 如图, 之前由于事务1回滚,导致事务2的 提交更新 丢失,但这种隔离级别下, 事务2 的 Write 操作,只能在事务 1,commit之后,或者rollback之后,所以能解决。
时刻 | 事务1 | 事务2 |
T1 | Read: N = 10 | Read : N = 10 |
T2 | Write: N = 11 | |
T3 | Rollback : N = 10 | |
T4 | Write: N = 9 | |
T5 | Commit: N = 9 |
但是对于第二类丢失更新问题不能解决:由于它们在同一时刻,读取到N,事务2提交后,事务1才能进行写 和提交,这样 事务2 提交的 跟新就丢失了。
时刻 | 事务1 | 事务2 |
T1 | Read: N = 10 | Read : N = 10 |
T2 | Wtrite : N = 9 | |
T3 | Commit: N = 9 | |
T4 | Write : N = 11 | |
T5 | Commit: N = 11 |
RC事务隔离级别,仍然存在 不可重读读的问题, 如下图(T1 时刻 事务 1 和事务 2 同时读到 N, 事务 2, 在事务 1提交后再次读 N,导致事务2 两次读取到不一致的数)
时刻 | 事务1 | 事务2 |
T1 | Read: N = 10 | Read : N = 10 |
T2 | Write: N = 11 | |
T3 | Commit : N = 11 | |
T4 | Read : N = 11 | |
T5 |
RR: (可重复读):指的是同一个事务中发出的同一个select语句(两次或更多次),那么产生的结果数据集总是相同的, 在RR级别中可能出现 幻读。
RR的实现原理:是基于MVCC实现不可重复读。
Serializable:串行化
实现原理:读的时候加共享锁,也就是其他事务可以并发读,但是不能写。 写的时候加排他锁,其他事务不能并发写 也不能并发读。