一、概述
事务
是多个操作在逻辑上构成一组操作,要么全部执行,要么全部不执行
.
Spring 事务本质:对数据库事务的包装
二、事务四大特性( ACID )
1. Atomicity(原子性)
- 事务是一个不可分割的整体,事务中的操作要么全部成功,要么全部失败
- 事务是一个不可分割的整体,事务中的操作要么全部成功,要么全部失败
2. Consistency(一致性)
- 在一个事务执行之前和执行之后,数据库都必须处于一致性状态
- 原子性、隔离性、持久性 同时满足来保证一致性
3. Isolation(隔离性)
- 一个事务的执行不应该影响其他事务的执行,事务与事务之间要做数据隔离
4. Durability(持久性)
- 一个事务一旦被提交,它对数据库中数据的改变就是永久性的
事务的最终目的:
数据一致性
分布式事务最终目的:
数据的最终一致性
三、事务五种隔离级别
1. DEFAULT
(默认选项)2. READ_UNCOMMITTED(未提交读)
3. READ_COMMITTED(已提交读)
4. REPEATABLE_READ(可重复读)
5. SERIALIZABLE(串行化、序列化)
四、事务七大传播行为
前置说明
若A()、B()方法都启用了事务
- A()方法的事务,称为:
当前事务(外部事务)
- B()方法的事务,称为:
嵌套事务(内部事务)
1. REQUIRED
若存在当前事务 则加入当前事务;
若当前没有事务 则开启一个新事务
2. SUPPORTS
如果存在当前事务 则加入当前事务;
若当前没有事务 则以非事务方法执行
3. MANDATORY
如果存在当前事务 则加入当前事务;
若当前没有事务 则抛出异常
4. REQUIRES_NEW
总是新开启一个事务
若当前存在事务时, 将当前事务挂起并新开启一个事务, 此时内部事务的回滚/异常 会影响外部事务
, 外部事务不会影响内部事务
;
5. NOT_SUPPORTED
表示以非事务的方式来运行, 若存在当前事务, 则把当前事务挂起;
6. Never
表示不以事务的方式运行, 若当前存在事务, 则抛出异常
7. Nested
若没有外部事务 就新建一个事务,若有外部事务,则嵌套
在当前事务中执行;
外部事物的回滚/异常 会影响内部事务, 内部事务的回滚不会影响外部事务
五、事务失效场景
Spring 事务在以下这些场景下,会失效
事务方法未被Spring管理
方法使用final类型修饰
Spring事务底层使用了AOP,也就是通过JDK动态代理或者cglib,帮我们生成了代理类,在代理类中实现的事务功能。但如果某个方法用final修饰了,那么在它的代理类中,就无法重写该方法,从而无法添加事务功能。这种情况事务就会在Spring中失效。
💡Tips: 如果某个方法是static的,同样无法通过动态代理将方法声明为事务方法。非public方法
非public的方法AOP也无法做代理增强调用本类的方法
spring的事务实现是使用了代理类来实现,假设TestService
类中a()方法调用本地方法 b(),就算b()方法加了@transactional注解, 但是实际上并没有走TestService的代理类,所以事务会失效抛出捕捉非运行时异常
数据库不支持事务
项目未配置开启事务
多线程,事务会失效
Spring的事务是通过ThreadLocal
来保证线程安全的,事务和当前线程绑定,多个线程自然会让事务失效
六、Spring 事务源码分析
- Spring 提供了对数据库的事务包装
- Spring 事务 =
Spring AOP
+数据库事务
1. Spring事务处理基本流程
- 1). 在类和方法上添加@Tranactional
- 2). Spring在启动时,会去解析生成相关的Bean
- 3). 最后Spring调用MySQL ( 或其他数据库 ) API,完成事务处理
2. 注解 @Transactional
作用
- 标识在对应的方法上,告知 Spring 这个目标方法需要被代理
- 携带事务管理需要的一些属性信息
Spring Boot
TransactionAutoConfiguration
1). TransactionAutoConfiguration
是Spring Boot
关于事务的自动配置类
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({PlatformTransactionManager.class})
@AutoConfigureAfter({JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class})
@EnableConfigurationProperties({TransactionProperties.class})
public class TransactionAutoConfiguration {
@Configuration
- 配置类
@ConditionalOnClass(PlatformTransactionManager.class)
- 当前类路径下存在 PlatformTransactionManager.class 时该配置生效
@AutoConfigureAfter({ JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class,Neo4jDataAutoConfiguration.class })
- 在 JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class,Neo4jDataAutoConfiguration.class 之后才解析该类.
@EnableConfigurationProperties(TransactionProperties.class)
可通过以下2个属性来配置:
- spring.transaction.defaultTimeout–> 配置事务的默认超时时间
spring.transaction.rollbackOnCommitFailure–> 配置是否在事务提交失败时回滚
- spring.transaction.defaultTimeout–> 配置事务的默认超时时间
2). 其中两个内部类
a. EnableTransactionManagementConfiguration
public class TransactionAutoConfiguration {
此处省略.....
// 标注为配置类
@Configuration(proxyBeanMethods = false)
// beanFactory 中存 TransactionManager 类型的bean时该配置生效
@ConditionalOnBean({TransactionManager.class
// beanFactory 不存在 AbstractTransactionManagementConfiguration 类型的bean时生效
@ConditionalOnMissingBean({AbstractTransactionManagementConfiguration.class})
public static class EnableTransactionManagementConfiguration {
....
@Configuration(proxyBeanMethods = false)
// TransactionManagement, proxyTargetClass = true,表示是使用cglib进行代理
@EnableTransactionManagement(proxyTargetClass = true)
// 其中, 当配置有 spring.aop.proxy-target-class 时,
// havingValue = true 代表当 spring.aop.proxy-target-class 的value 值 为 true, 则该代理生效
@ConditionalOnProperty(
prefix = "spring.aop",
name = {"proxy-target-class"},
havingValue = "true",
matchIfMissing = true
)
public static class CglibAutoProxyConfiguration {
public CglibAutoProxyConfiguration() {
}
}
@Configuration(proxyBeanMethods = false)
// TransactionManagement, proxyTargetClass = false,表示是面向接口代理, 使用JDK的实现
@EnableTransactionManagement(proxyTargetClass = false)
// 其中, 当配置有 spring.aop.proxy-target-class 时,
// havingValue = true 代表当 spring.aop.proxy-target-class 的value 值 为 false, 则该代理生效
// 默认使用的该实现进行代理
@ConditionalOnProperty(
prefix = "spring.aop",
name = {"proxy-target-class"},
havingValue = "false",
matchIfMissing = false
)
public static class JdkDynamicAutoProxyConfiguration {
public JdkDynamicAutoProxyConfiguration() {
}
}
}
}
因此,在默认情况下, EnableTransactionManagementConfiguration
生效的是 JdkDynamicAutoProxyConfiguration
.
b. TransactionTemplateConfiguration
public class TransactionAutoConfiguration {
此处省略.....
@Configuration(proxyBeanMethods = false)
// PlatformTransactionManager类型的bean存在并且当存在多个bean时指定为Primary
// 的PlatformTransactionManager存在时,该配置类才进行解析
@ConditionalOnSingleCandidate(PlatformTransactionManager.class)
public static class TransactionTemplateConfiguration {
public TransactionTemplateConfiguration() {
}
// 当 beanFactory 中不存在 TransactionOperations 类型的bean时,
// 注册一个id为 transactionTemplate,类型为 TransactionTemplate 的 bean
// TransactionTemplate 实现了 TransactionOperations
@Bean
@ConditionalOnMissingBean({TransactionOperations.class})
public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
return new TransactionTemplate(transactionManager);
}
}
}
由于 TransactionAutoConfiguration
是在 DataSourceTransactionManagerAutoConfiguration
之后才被解析处理的, 而在DataSourceTransactionManagerAutoConfiguration
中配置了 transactionManager
,因此, TransactionTemplateConfiguration
会被处理.