目录
事务的隔离性
事务的隔离级别
读未提交
读已提交
可重复读
串行化
Spring事务的传播机制
支持当前事务
不支持当前事务
嵌套事务
事务的隔离性
事务的隔离性是事务的四大特性之一,数据库允许多个事务并发操作数据,为了尽可能地避免并发操作数据所带来的隐患,就需要依赖于事务地隔离性。事务的隔离性分为多个等级,包括:读未提交、读已提交、可重复读以及串行化,隔离等级依次提高。隔离性也是事务四大特性中唯一一个可以设置级别的特性。
事务的隔离级别
读未提交
事务最低隔离级别,该级别事务可以读取别的事务未提交时的数据。未提交的数据可能发生回滚,这时读取到的数据就是不存在的,这个数据称为脏数据,这个问题称为脏读;
读已提交
该级别的事务读取到的数据都是提交过的数据,因此不会出现脏读问题。但是在该事务读取数据时,别的事务可以提交事务,因此在这次的事务中,可能出现使用同样的查询语句,查询出的结果却不同,这种现象称为不可重复读:
可重复读
可重复读是MySQL默认的事务隔离级别,在此级别的事务执行过程中,其他的事务不能操作(包括读和写)已有的数据,因此不会出现不可重复读的情况(实际上该事务创建了一个快照,读取的数据都是基于这个快照的,而不是数据本身,因此事务对数据的修改在未提交时其他事务是看不到的)。但是却可以插入新的数据,这样相同的查询语句,返回的结果集就可能不同,这种情况就称为幻读:
串行化
事务隔离的最高级别,强制事务串行执行,没有并发操作,自然不会出现脏读、不可重复读和幻读的情况。
不可重复读和幻读的区别:
- 不可重复读指的是某条数据被修改(包括删除)而造成的前后读取不一致的情况
- 幻读指的是由于新插入数据导致读取的数据集不一致。
Spring事务的传播机制
事务的隔离级别保证事务并发执行的稳定性,而事务的传播机制则保证一个事务在多个方法调用时的稳定性。在实际开发中,很少会直接通过事务来操作数据库中的数据,往往会有一条调用链,层层传递:
Spring事务的传播机制大体可分为三类:支持当前事务、不支持当前事务和嵌套事务。
支持当前事务
- Propagation.REQUIRED: Spring事务的默认传播机制,如果当前调用链已经存在事务,则把该方法或节点加入事务;如果不存在事务,创建事务;
- Propagation.SUPPORTS: 如果当前调用链已经存在事务,则把该方法或节点加入事务;如果不存在事务,以非事务方式执行;
- Propagation.MANDATORY: 如果当前调用链已经存在事务,则把该方法或节点加入事务;如果不存在事务,抛异常;
不支持当前事务
- Propagation.REQUIRES_NEW: 创建新事务;如果当前调用链已经存在事务,把当前事务挂起,并创建新事务,新事务执行完再执行当前事务;
- Propagation.NOT_SUPPORTED: 以非事务方式运行;如果当前存在事务,把当前事务挂起;
- Propagation.NEVER: 以非事务方式运行;如果当前存在事务,抛异常;
嵌套事务
Propagation.NESTED: 当前存在事务,则创建事务嵌套进去;如果不存在事务,则创建事务;
这里的嵌套事务和上述加入事务不同,加入事务就成为一个整体,要么全部成功,要么全部失败;而嵌套事务可以一起成功,但如果嵌套的事务执行失败了,只回滚嵌套的事务,外部事务的提交不受影响。
假如调用链上某个方法或节点不指定事务的传播机制,则遵循其上层节点或方法的事务传播机制。