就这?一篇文章让你读懂 Spring 事务
什么是事务
什么是事务
▲ 百度百科
事务的特性
提到事务,不可避免需要涉及到事务的四个特性(ACID):
原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。
我们将严格遵循 ACID 属性的事务称为刚性事务。与之相对,期望最终一致性,在事务执行的中间状态允许暂时不遵循 ACID 属性的事务称为柔性事务,柔性事务的使用涉及到分布式事务方案,后续将为大家扩展,这里就不过多阐述。
Spring 事务管理的方式
2、声明式事务管理
声明式事务管理建立在 AOP 之上,有两种常用的方式,一是基于 tx 和 aop 命名空间的 xml 配置文件,一是基于 @Transactional 注解,随着 Spring 和 Java 的版本越来越高,越趋向于使用注解的方式。
其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,执行完目标方法之后根据执行的情况提交或者回滚。
声明式事务属于无侵入式,不会影响业务逻辑的实现,只需要在配置文件中做相关的事务规则声明或者通过注解的方式,便可以将事务规则应用到业务逻辑中。而编程式事务每次实现都要单独实现,但业务量大功能复杂时,使用编程式事务无疑是痛苦的。
顺便了解下注解 @Transactional 的作用范围:
方法 :推荐将注解使用于方法上,不过需要注意的是:该注解只能应用到 public 方法上,否则不生效。
类 :如果这个注解使用在类上的话,表明该注解对该类中所有的 public 方法都生效。
接口 :不推荐在接口上使用。
Spring 事务管理的五大属性
当有多个事务同时执行时,就可能出现下面这些问题:
-
脏读: 一个事务读取了另一个事务未提交的数据。 -
不可重复读: 一个事务先后读取相同的数据,发现两次读取的数据内容不一致。 -
幻读: 一个事务按相同的查询条件重新读取以前检索过的数据,却发现其它事务插入了满足其查询条件的新数据
而事务的隔离级别就定义了并发事务活动影响的程度。
-
ISOLATION_DEFAULT:使用后端数据库默认的隔离级别(MySQL 默认采用的REPEATABLE_READ 隔离级别 Oracle 默认采用的 READ_COMMITTED 隔离级别) -
ISOLATION_READ_UNCOMMITTED: 允许读取尚未提交的更改,这是最低的隔离级别,很少会使用。可能导致脏读、幻读或不可重复读。 -
ISOLATION_READ_COMMITTED: 允许从已经提交的并发事务读取。可防止脏读,但幻读和不可重复读仍可能会发生。 -
ISOLATION_REPEATABLE_READ: 对相同字段的多次读取的结果是一致的,除非数据被当前事务本身改变。可防止脏读和不可重复读,但幻读仍可能发生。 -
ISOLATION_SERIALIZABLE: 最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这在所有隔离级别中也是性能最差的,因为它通常是通过完全锁定当前事务所涉及的数据表来完成的。通常情况下也不会用到该级别。
2、事务的传播机制
PROPAGATION_REQUIRED(默认):
如果该方法执行在没有事务的方法中,就创建一个新的事务。
如果执行在已经存在事务的方法中,则加入到这个事务中,合并成一个事务。
PROPAGATION_SUPPORTS:
如果该方法执行在没有事务的方法中,就以非事务方式执行。
如果执行在已经存在事务的方法中,则加入到这个事务中,合并成一个事务。
PROPAGATION_MANDATORY:
如果该方法执行在没有事务的方法中,就抛出异常。
如果执行在已经存在事务的方法中,则加入到这个事务中,合并成一个事务。
PROPAGATION_REQUIRES_NEW:
无论该方法是否执行在事务的方法中,都创建一个新的事务。
不过如果执行在存在事务的方法中,就将方法中的事务暂时挂起。
新的事务会独立提交与回滚,不受调用它的父方法的事务影响。
PROPAGATION_NOT_SUPPORTED:
无论该方法是否执行在事务的方法中,都以非事务方式执行。
不过如果执行在存在事务的方法中,就将该事务暂时挂起。
PROPAGATION_NEVER:
如果该方法执行在没有事务的方法中,就也以非事务方式执行。
不过如果执行在存在事务的方法中,就抛出异常。
PROPAGATION_NESTED:
如果该方法执行在没有事务的方法中,就创建一个新的事务。
如果执行在已经存在事务的方法中,则在当前事务中嵌套创建子事务执行。
被嵌套的事务可以独立于封装事务进行提交或回滚。
如果外部事务提交嵌套事务也会被提交,如果外部事务回滚嵌套事务也会进行回滚。
4、事务超时
事务超时指的是一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,就会自动回滚事务,避免长时间运行的事务会不必要地占用数据库资源。
往期推荐