浅谈对Spring事务的认识:https://xiaoer.blog.csdn.net/article/details/80849971
一、事务的特性
事务是数据库永恒不变的话题, ACID:原子性,一致性,隔离性,持久性。
(1)原子性(Atomicity):事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用。
(2)一致性(Consistency):一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败。在现实中的数据不应该被破坏。
(3)隔离性(Isolation):可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。
(4)D-持久性(Durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,这样就能从任何系统崩溃中恢复过来。通常情况下,事务的结果被写到持久化存储器中。
四个特性,最重要的就是一致性。而一致性由原子性,隔离性,持久性来保证。
(1)原子性由 Undo log 保证。Undo Log 会保存每次变更之前的记录,从而在发生错误时进行回滚。
(2)隔离性由 MVCC 和 Lock 保证。
(3)持久性由 Redo Log 保证。每次真正修改数据之前,都会将记录写到 Redo Log 中,只有 Redo Log 写入成功,才会真正的写入到 B+ 树中,如果提交之前断电,就可以通过 Redo Log 恢复记录。
二、事务的隔离级别
MySQL数据库隔离级别:未提交读(RU)、已提交读(RC)、可重复读(RR)、串行化(serializable)。每个级别都会解决不同的问题,通常是3 个问题:脏读,不可重复读,幻读。
(1)READ_UNCOMMITTED:读未提交,最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
(2)READ_COMMITTED:读已提交,允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
(3)REPEATABLE_READ:可重复读,对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生
(4)SERIALIZABLE:串行化,最高的隔离级别,完全服从ACID的隔离级别,确保阻止脏读、不可重复读以及幻读,也是最慢的事务隔离级别,因为它通常是通过完全锁定事务相关的数据库表来实现的
注意点:关于幻读,在数据库规范里,RR 级别会导致幻读,但是,由于 Mysql 的优化,MySql 的 RR 级别不会导致幻读:
三、事务的原理剖析
1、RU 发生脏读的原因
RU 原理是对每个更新语句的行记录进行加锁,而不是对整个事务进行加锁,所以会发生脏读。而 RC 和 RR 会对整个事务加锁。
2. RC 不能重复读的原因
RC 每次执行 SQL 语句都会生成一个新的 Read View,每次读到的都是不同的。而 RR 的事务从始至终都是使用同一个 Read View。
3、RR 不会发生幻读的原因
在使用默认的 select 时,MySql 使用 MVCC 机制保证不会幻读;当然可以使用锁,在使用锁时,例如 for update(X 锁),lock in share mode(S 锁),MySql 会使用 Next-Key Lock 来保证不会发生幻读。前者称为快照读,后者称为当前读。
参考:《MYSQL:简述多版本并发控制MVCC》
4、RR 和 Serializble 的区别
RR会造成丢失更新,Serializble可以避免这种情况。