1. 事务的基本概念
1.1简介
- 数据库事务是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
- Spring的事务管理主要基于AOP(面向切面编程)技术,通过声明式或编程式的方式来实现。
- Spring框架内部使用事务管理器的接口PlatformTransactionManager,来完成commit和rollback
- 针对不同的框架,提供不同的实现类
1.2ACID属性
- 原子性(Atomicity):事务是一个原子操作单元,其对数据的修改要么全都执行,要么全都不执行。
- 一致性(Consistency):事务必须使数据库从一个一致性状态变换到另一个一致性状态。
- 隔离性(Isolation):在事务开始到事务结束前的中间过程中,由于隔离机制的存在,所以事务中所使用的数据资源都不会被其他事务所访问。
- 持久性(Durability):一旦事务提交,则其结果就是永久性的,即使系统发生崩溃,事务执行的结果也不能被撤销。
2. Spring事务管理的实现方式
- Spring提供了两种主要的事务管理方式:声明式事务管理和编程式事务管理。
2.1 声明式事务管理
- 基于XML配置:通过在Spring配置文件中配置<tx:advice>和<aop:config>等元素,将事务管理切面应用到指定的方法上。
- 基于注解:使用@Transactional注解在需要事务管理的方法或类上标记,Spring会自动为这些方法或类添加事务管理。
2.2 编程式事务管理
- 编程式事务管理需要开发者在代码中显式地调用事务管理的方法,如PlatformTransactionManager的getTransaction、commit和rollback等。
- 这种方式相对繁琐,且不利于代码的解耦和重用,因此在实践中较少使用。
3. Spring事务管理器
Spring提供了多种事务管理器,用于支持不同的事务处理策略和数据源。常见的事务管理器有:
- DataSourceTransactionManager:用于JDBC数据源的事务管理。
- HibernateTransactionManager:用于Hibernate框架的事务管理。
- JpaTransactionManager:用于JPA框架的事务管理。
- JtaTransactionManager:用于支持全局事务的JTA(Java Transaction API)环境。
4.事务的隔离级别
- Spring支持四种事务隔离级别,这些级别可以通过@Transactional注解的isolation属性来设置。
- 不同的隔离级别对事务的并发性和性能有不同的影响。
级别 | 描述 |
ISOLATION_DEFAULT | 默认级别, mysql 数据库 ISOLATION_REPEATABLE_READ,Oracle 数据库默认级别 ISOLATION_READ_COMMITTED |
ISOLATION_READ_UNCOMMITTED | 读未提交,没有解决并发问题 |
ISOLATION_READ_COMMITTED | 读已提交,解决脏读 |
ISOLATION_REPEATABLE_READ | 可重复读,解决脏读、不可重复读 |
ISOLATION_SERIALIZABLE | 串行化,不会产生并发问题 |
5. 事务的传播行为
- Spring定义了7种事务的传播行为,用于指定当前方法被另一个事务方法调用时,应该如何处理事务。
- 这些传播行为可以通过@Transactional注解的propagation属性来设置。
7种事务的传播行为:
传播行为 | 描述 |
PROPAGATION_REQUIRED | 如果当前没有事务,则创建一个新的事务,如果当前存在 事务,则加入到这个事务中。 |
PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,则以非事务方式执行 |
PROPAGATION_REQUIRED_NEW | 新建事务,如果当前事务存在,则把当前事务挂起 |
PROPAGATION_MANDATORY | 使用当前的事务,如果当前没有事务,则抛出异常 |
PROPAGATION_NOT_SUPPORTS | 以非事务方式进行操作,如果当前存在事务,则把当前事务挂起 |
PROPAGATION_NEVER | 以非事务方式进行操作。如果当前存在事务,则抛出异常 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行,如果当前没有事务,则执行的方式与PROPAGATION_REQUIRED类似的操作 |
分析 REQUIRED\ REQUIRED_NEW \ NESTED 差别
异常状态 | REQUIRED_NEW( 两个独立事务 ) | REQUIRED( 同一个事务 ) | NESTED(B的事务嵌 套在 A 中 ) |
methodA 抛异常 methodB 正常 | A 回滚, B 正常提交 | A 与 B 同时回滚 | A 与 B 同时回滚 |
methodA 正常 methodB 抛异常 | 1 、如果 A 中捕获 B 的异常,并没有继续向上抛异常,则 B 先回滚, A 正常提交; 2 、如果 A 未 捕获 B 的异常,默认则会将 B 的异常向上抛出, 则 B 先回滚, A 再回滚 | A与B同时回滚 | B 先回滚, A 正常提交 |
methodA 抛异常 methodB 抛异常 | B 先回滚, A 再回滚 | A与B同时回滚 | A与B同时回滚 |
methodA 正常 methodB 正常 | B 先提交, A 再提交 | A与B同时提交 | A与B同时提交 |
6. 事务的回滚规则
- 默认情况下,Spring会在运行时异常(RuntimeException)和错误(Error)发生时回滚事务。
- 如果需要自定义回滚规则,可以通过@Transactional注解的rollbackFor和noRollbackFor属性来指定。
7. 使用注意事项
- 确保数据源和事务管理器正确配置。
- 合理使用事务的传播行为和隔离级别。
- 注意事务的边界和嵌套使用。
- 避免在事务中执行非数据库操作(如发送邮件、调用远程服务等),以免破坏事务的原子性。
- 对于只读操作,可以设置事务为只读模式以提高性能。