简介
事务是恢复和并发控制的基本单位,其具备4个属性:原子性(atomicity)、一致性(consistency)、隔离性(isolation)、隔离性(durability)、持久性。这四个属性通常称为ACID特性。
原子性:一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
一致性:事务必须使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性:一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性:持久性也称为永久性,只一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
事务并发问题
丢失更新:撤销一个事务时,把其他事务已提交的更新的数据覆盖了。
脏读:一个事务读到另一个事务未提交的更新数据。
不可重复读:一个事务两次都同一行数据,可是这两次读到的数据不一样。
幻读:一个事务执行两次查询,但第二次查询比第一次查询多出了一些数据行。
隔离级别
Read Uncommitted: 读未提交数据,隔离级别最差,存在脏读、不可重复读、幻读的问题。
Read Committed: 读已提交数据,存在不可重复读,幻读的问题。
Repeatable Read: 可重复读,存在幻读的问题。
Serializable:串行化,问题都不存在。
关键接口
PlatformTransactionManager: 事务管理器;
TransactionDefinition:事务的一些的基础信息,如超时时间、隔离级别、传播属性等;
TransactionStatus: 事务的一些状态信息,如是否是一个新的事务、是否已被标记为回滚。
事务在Spring中是如何运作的
了解嵌套事务之前,可以先看下单个事务在spring中的处理流程,以便后面可以更清晰地认识嵌套事务的逻辑。
Spring事务使用AOP的机制实现,会在@Transactional注解修饰的方法前后分别织入开启事务的逻辑,以及提交和回滚的逻辑。
当出现多个事务嵌套的场景发生时,Spring事务的处理会变得复杂一下,需要考虑事务下的提交顺序,以及回滚顺序,对此,Spring提供了多种传播机制,每种传播机制的效果都不尽相同,以便应对各种复杂的业务场景。
嵌套事务处理流程如下:
主事务开启->主事务执行->子事务开启->子事务执行->子事务提交或回滚->主事务提交或回滚(根据事务传播机制配置来判断)。
Spring事务传播机制
事务的传播机制,主要是决定业务方法之间调用,事务应该如何处理。
required: 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务,默认值。
required_new: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。
supports: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
not_supports: 以非事务方式运行,如果但钱存在事务,则把当前事务挂起。
mandatory:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
never: 以非事务方式运行,如果当前存在事务,则抛出异常。
NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则等价于required。
事务的几种实现方式
基于xml配置方式的事务管理
基于注解方式的事务管理(声明式事务)
@Transactional 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。
虽然 @Transactional 注解可以作用于接口、接口方法、类以及类方法上,但是 Spring 建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。另外, @Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的。如果你在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常。
默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰。
关于@Transactional注解中的默认值
只读属性为false,传播行为是TransactionDefinition.PROPAGATION_REQUIRED,隔离级别是TransactionDefinition.ISOLATION_DEFAULT,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是TransactionDefinition.ISOLATION_READ_COMMITTED。所以注解的默认值足够我们项目中使用,我们只用在类前面打上注解就可以了。
基于编程式事务管理
编程式事务使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。
对于编程式事务管理,spring推荐使用TransactionTemplate。
引用
https://www.cnblogs.com/qlqwjy/p/7296493.html