SpringBoot设置事务管理@Transactional以及事务失效的情况
- 事务介绍
- Atomicity(原子性):事务中的所有操作要么全做要么全不做
- Consistency(一致性):事务执行的结果使得数据库从一个一致性状态转移到另一个一致性状态
- Isolation(隔离性):一个事务的执行不受其他事务的干扰
- Durability(永久性):一个事务一旦提交,对数据库的影响是永久性的
- 什么是脏读?不可重复读?幻读?
- 脏读(Dirty Read):一个事务读取到另外一个事务未提交的数据。举例:一个事务1读取了被另一个事务2修改但还未提交的数据。由于某种异常事务2回滚,则事务1读取的是无效数据。
- 不可重复读(Non-repeatable read):一个事务读取同一条记录2次,得到的结果不一致。这可能是两次查询过程中间,另一个事务更新了这条记录。
- 幻读(Phantom Read):幻读发生在两个完全相同的查询,得到的结果不一致。这可能是两次查询过程中间,另一个事务增加或者减少了行记录。
- 不可重复度和幻读区别:不可重复读的重点是修改,幻读的重点在于新增或者删除。
- 事务隔离级别
- READ-UNCOMMITTED(读未提交):最低的隔离级别,一个事务可以读取另一个事务更新但未提交的数据。可能会导致脏读、不可重复读或幻读。
- READ-COMMITTED(读已提交):一个事务提交后才能被其他事务读取到,可以阻止脏读,但是不可重复读或幻读仍有可能发生。
- REPEATABLE-READ(可重复读):对同一记录的多次读取结果都是一致的,除非数据是被本身事务所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
- SERIALIZABLE(可串行化):最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
- MySQL 默认采用的 REPEATABLE-READ(可重复读)隔离级别,Oracle 默认采用的READ-COMMITTED(读已提交)隔离级别
- InnoDB 存储引擎在分布式事务的情况下一般会用到SERIALIZABLE(可串行化)隔离级别。
- 在Spring Boot中推荐使用@Transactional注解来申明事务。
- 首先需要导入依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
- 当引入jdbc依赖之后,Spring Boot会自动默认分别注入DataSourceTransactionManager或JpaTransactionManager,所以我们不需要任何额外配置就可以用@Transactional注解进行事务的使用。
*使用动态数据源的时候需要设置自己的事务管理器,如下:
@Bean public PlatformTransactionManager transactionManager() { // 配置事务管理, 使用事务时在方法头部添加@Transactional注解即可 return new DataSourceTransactionManager(dynamicDataSource()); }
- 首先需要导入依赖:
- 事务失效的情况
- 数据库引擎不支持事务,其MyISAM引擎是不支持事务操作的mysql要在5.5以后
- 没有被Spring管理, @Service 注解注释掉,这个类就不会被加载成一个 Bean,那这个类就不会被 Spring 管理了,事务自然就失效了
- 方法不是public的@Transactional 只能用于 public 的方法上,否则事务不会失效,如果要用在非 public 方法上,可以开启 AspectJ 代理模式。
- 自身调用问题:非事务方法调用直接调用事务方法
- 数据源没有配置事务管理器
- 不支持事务,主动不支持以事务方式运行
- 异常被吃了,捕获了异常却不抛出来
- 抛出异常类型不对:因为默认回滚的是:RuntimeException,如果你想触发其他异常的回滚,需要在注解上配置一下,如:@Transactional(rollbackFor = Exception.class)