事务的特性
1 | markdown复制代码 - 原子性: 原子性是事务的最小执行单位,事务的原子性确保动作要么全部执行完毕,要么就都不执行 |
spring事务管理接口
1 | markdown复制代码 - PlatformTransactionManager 平台事务管理器 |
PlatformTransactionManager接口介绍
spring 并不直接管理事务,而是提供多种事务管理器,具体的实现交于JTA等持久化机制所提供的平台框架去实现
spring事务管理器的接口是:org.springframework.transaction.PlatformTransactionManager,为各个平台提供事务管理器,具体的实现就需要平台自己实现,
PlatformTransactionManager提供了三个方法
1 | java复制代码public interface PlatformTransactionManager { |
TransactionDefinition介绍
TransactionDefinition中定义了事务的传播行为、隔离级别、超时、只读、回滚规则。 TransactionDefinition中有5个方法以及一些关于传播行为和隔离级别的常量
1 | ini复制代码public interface TransactionDefinition { |
TransactionStatus介绍
TransactionStatus中有五个方法,用于来获取事务的状态
1 | csharp复制代码public interface TransactionStatus extends SavepointManager, Flushable { |
事务的传播行为
事务的传播行为是为了解决业务层之间互相调用的事务问题,当事务方法被另一个事务方法调用时,是在现有的事务中运行,还是创建一个新的事务来运行,在TransactionDefinition中定义了7个传播行为的常量
支持当前事务
- PROPAGATION_REQUIRED :如果当前存在事务,则加入该事务,如果不存在事务,则创建一个新的事务运行。
- PROPAGATION_SUPPORTS :如果当前存在事务,则加入该事务,如果不存在事务,则以非事务的方式运行。
- PROPAGATION_MANDATORY :如果当前存在事务,则加入该事务,如果不存在事务,则抛出异常。(MANDATORY:强制性)
不支持当前事务
- PROPAGATION_REQUIRES_NEW :创建一个新的事务运行,如果当前存在事务的话,则将当前事务挂起。
- PROPAGATION_NOT_SUPPORTED :以非事务的方式运行,如果当前存在事务的话,则将当前事务挂起。
- PROPAGATION_NEVER :以非事务的方式运行,如果当前存在事务的话,则抛出异常
其他情况
- PROPAGATION_NESTED :如果当前存在事务的话,则创建一个嵌套事务来运行,可以理解为子事务,多个子事务之间互不影响,外部事务回滚子事务不会回滚,子事务回滚外部事务也会回滚,子事务不可以单独提交,他依赖于外部事务,只有通过外部事务的提交,才可以提交子事务
事务的隔离级别
事务的的隔离级别定义了再并发访问下受其他事务所影响的程度,先让我们来看看并发事务下会出现哪些问题
- 脏读: 当一个事务获取数据并修改了数据,但还未提交到数据库中,此时另一个事务获取到了数据, 然后使用了该数据,因为这个数据是还未提交到数据库中,因此第二个事务读取到的数据就是”脏数据”,基于脏数据的操作结果可能是不正确的
- 丢失修改: 一个事务在获取数据时,另一个事务也获取了该数据,第一个事务修改了数据并提交到数据库中,另一个事务也修改了数据并提交到数据库中,此时第二个事务修改的数据会覆盖第一个事务修改的数据,造成第一个事务的修改丢失
- 不可重复读: 当一个事务多次读取数据时,在此事务还没有结束时,另一个事务在此事务两次读取数据之间获取了该数据并进行了修改,此时此数据前后读取到的数据时不一致的,因此成为不可重复读
- 幻读: 幻读和不可重复读类似,在事务一读取多条数据时,此时事务二向数据库中插入了新数据,在事务一后面的查阅中会多出一些原本不存在的数据,就好像出现幻觉一样,一次称为幻读
不可重复读和幻读的区别
不可重复读的重点在于修改,幻读的重点在于新增或者删除
例1: 当事务1中的A用户去读取的自己的工资为1000的操作还没有完成时,事务2中的B用户将A用户的工资改为2000,导致A在读取自己的工资为2000,这就称为不可重复读
例2:在事务1中去查询工资大于2000的员工,第一次查询为只有4人,此时事务二新增一条工资大于2000的员工数据,此时事务1再次读取数据变成了5条,这称为幻读
spring 事务隔离级别
- ISOLATION_DEFAULT: 使用数据库自带的默认隔离级别,mysql默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别
- ISOLATION_READ_UNCOMMITTED: 最低的隔离级别,允许读取未提交的数据变更,可能会产生脏读、不可重复读、幻读等问题
- ISOLATION_READ_COMMITTED: 只允许读取已提交的数据,可以阻止脏读,可能会产生不可重复读、幻读等问题
- ISOLATION_REPEATABLE_READ: 对多次读取的结果必须一致,除非时同一个事务所修改的,可以阻止脏读、不可重复读,可能会产生幻读等问题
- ISOLATION_SERIALIZABLE: 最高隔离级别,每个事务必须逐个执行,根本不可能产生脏读、丢失修改、不可重复读、幻读等问题,但是严重影响了程序性能,实际开发中基本不用这个隔离级别
事务超时属性
事务超时属性定义了事务最大的执行时长,超过执行时长事务会自动回滚,其单位为秒
事务只读属性
事务只读属性标记着对事务性资源只读操作或读写操作,所谓的事务性资源就是数据源、JMS资源以及自定义的事务性资源,如果确定对事务性资源只读操作,那么可以将事务只读属性标记为true,以提高事务处理性能
回滚规则
回滚规则定义了哪些异常会回滚,哪些异常不会回滚,默认情况下只有运行时异常才会回滚,我们可以自定义那些异常回滚,也可以自定义哪些异常不回滚
spring 支持两种方式的事务管理
- 编程式事务管理
编程式事务管理在实际开发中,几乎不会用到,大多数情况下我们通过注解式事务管理,我们可以使用TransactionTemplate和PlatformTransactionManager来手动管理事务
TransactionTemplate方式
1 | typescript复制代码@Resource |
PlatformTransactionManager方式
1 | typescript复制代码@Resource |
声明式事务管理
1 | less复制代码@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) |
本文转载自: 掘金