隔离级别
传播行为
@Transactional标注
对于spring声明式事务,是使用@Transactional进行标注。这个注解可以标在方法和类(或接口)上,标注在类上时,表示该类的所有公共(public)非静态方法都将启用事务功能。
在@Transactional中,允许配置许多如事务的隔离级别和传播行为等属性。在Spring Ioc容器在加载时就会将这些配置信息解析出来,然后把这些信息存到事务定义器(TransactionDefinition接口的实现类)里,并且记录哪些类或方法需要启动事务功能,采取什么策略去执行事务。当Spring的上下文开始调用被@Transactional标注的类或方法时,spring就会产生AOP的功能。
如果发生异常,就要判断一次事务定义器中的配置,如果事务定义器已经约定了该类型的异常不回滚事务就提交事务,如果没有任何配置或不是配置不回滚事务的异常,则会回滚事务,并且抛出异常,这步也是事务拦截器完成的。
隔离级别
数据库事务的四个特征:ACID
- Atomic(原子性)
- Consistency(一致性)
- Isolation(隔离性)
- Durability(持久性)
第一类丢失更新:一个事务回滚另一个事务提交而引发的数据不一致的情况。
第二类丢失更新:多个事务都提交引发的丢失更新。
隔离级别
- 未提交读(read uncommitted)
- 读写提交(read committed)
- 可重复读
- 串行化(serializable)
项目类型 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
未提交读 | √ | √ | √ |
读写提交 | x | √ | √ |
可重复读 | x | x | √ |
串行化 | x | x | x |
方法使用隔离级别
@Transactional(isolation = Isolation.READ_COMMITTED,timeout = 1)//事务
public User getUser(Long id){
return userDao.getUserById(id);
}
application.properties配置项目默认隔离级别
#数据库隔离级别配置
#MySQL默认可重复读,Oracle默认读写提交
#-1 数据库默认
#1 未提交读
#2 读写提交
#3 可重复读
#4 串行化
spring.datasource.dbcp2.default-transaction-isolation=2
传播行为
批量任务我们称之为当前方法,那么批量事务就称为当前事务,当它调用单个交易时,称单个交易为子方法,当前方法调用子方法的时候,让每一个子方法不在当前事务中执行,而是创建一个新的事务去执行子方法,我们就说当前方法调用子方法的传播行为为新建事务。
@Transactional(isolation = Isolation.READ_COMMITTED,timeout = 1,
propagation = Propagation.MANDATORY)//事务
public User getUser(Long id){
return userDao.getUserById(id);
}
在Spring事务机制中对数据库存在7种传播行为,它是通过枚举类Propagation定义的。
- REQUIRED(需要的)
需要事务,它是默认传播行为。
如果当前存在事务,就沿用当前事务。
否则新建一个事务运行子方法 - SUPPORTS(支持的)
支持事务。
如果当前存在事务,就沿用当前事务。
否则继续采用无事务的方式运行子方法 - MANDATORY(强制的)
必须使用事务。
如果当前存在事务,就沿用当前事务。
如果当前没有事务,抛出异常。 - REQUIRES_NEW(创建新的)
无论当前事务是否存在,都会创建新事务运行方法。
这样新事务就可以拥有新的锁和隔离级别等特性,与当前事务相互独立。 - NOT_SUPPORTED(不支持)
不支持事务。
如果当前方法存在事务,就挂起事务,运行方法。 - NEVER(规定没有)
不支持事务。
如果当前方法存在事务,抛出异常。
否则继续采用无事务的方式运行。 - NESTED(嵌套的)
会沿用当前事务的隔离级别和锁等特性。
在当前方法调用子方法时,如果子方法发生异常,只回滚子方法执行过的SQL,而不回滚当前方法的事务。