全网疯传的Spring学习笔记【Spring事务】,看完我也想写一个了!
十一、事务
11.1、事务的属性
属性是描述物体特征的一系列值,事务有五个属性:
- 隔离属性
- 传播属性
- 只读属性
- 超时属性
- 异常属性
我们可以用@Transactional()
注解在添加属性,在括号被给事务添加属性。
11.2、隔离属性
隔离属性描述了事务解决并发问题的特征。事务并发访问会产生三个问题:
- 脏读
- 不可重复读、
- 幻读
我们可以通过隔离属性来解决事务并发产生的问题,在隔离属性中设置不同的值。
11.2.1、脏读
一个事务读取了另一个事务中没有提交的数据,会在本事务中产生数据不一致的问题。这个是Oracle的默认属性。
解决方案:给@Transactional()
注解添加isolation=Isolation.READ_COMMITTED
。
11.2.2、不可重复读
一个事务中,多次读取相同的数据,但是读取的结果不一样,会在本事务中产生数据不一致的问题。他读取的数据不是脏数据,只是查询的数据一致。这个是MySQL的默认属性。
解决办法:给@Transactional()
注解添加isolation=Isolation.REPEATABLE.READ
。他的本质是给该条数据加一把行级锁。
11.2.3、幻读
一个事务,多次对整表进行查询统计,但是结果的行数不一样,会在本事务中产生数据不一致的问题。
解决办法:给@Transactional()
注解添加isolation=Isolation.SERIALIZABLE
。他的本质是给整个表加一把表锁。
11.2.4、总结
并发安全排序:Isolation.SERIALIZABLE>Isolation.REPEATABLE.READ>Isolation.READ_COMMITTED
性能排序:Isolation.SERIALIZABLE<Isolation.REPEATABLE.READ<Isolation.READ_COMMITTED
# 我们可以用命令来查询MySQL的默认属性。
select @@tx_isolation
隔离属性的值 | MySQL | Oracle |
---|---|---|
ISOLATION_READ_COMMITTED | ✅ | ✅ |
IOSLATION_REPEATABLE_READ | ✅ | ❎ |
ISOLATION_SERIALIZABLE | ✅ | ✅ |
11.3、传播属性
传播属性描述了事务解决嵌套问题的特征。
事务嵌套:一个大的事务里面包含着几个小的事务。
事务嵌套由于大事务中融入了很多的小事务,他们彼此影响,最终就会导致外部的大事务丧失了事务的原子性。我们用传播属性的值来解决这个问题,传播属性的值保证了在同一时间只会有一个事务存在。
11.3.1、事务传播属性详解
融合:自己的事务没有了,以外部的事务为准。
挂起:相当于暂停。
传播属性的值 | 外部不存在事务 | 外部存在事务 | 用法 | 使用场景 |
---|---|---|---|---|
REQUIRED**(默认)** | 开启新的事务 | 融合到外部事务中 | @Transactional(propagation = Propagation.REQUIRED) | 增删改方法 |
SUPPORTS | 不开启事务 | 融合到外部事务中 | @Transactional(propagation = Propagation.SUPPORTS) | 查询方法 |
REQUIRES_NEW | 开启新的事务 | 挂起外部事务,创建新的事务。 | @Transactional(propagation = Propagation.REQUIRES_NEW) | 日志记录方法中 |
NOT_SUPPORTED | 不开启事务 | 挂起外部事务 | @Transactional(propagation = Propagation.NOT_SUPPORTED) | 及其不常用 |
NEVER | 不开启事务 | 抛出异常 | @Transactional(propagation = Propagation.NEVER) | 及其不常用 |
MANDATORY | 抛出异常 | 融合到外部事务中 | @Transactional(propagation = Propagation.MANDATORY) | 及其不常用 |
11.4、只读属性
针对只进行查询操作的业务方法,可以加入只读属性(readlyonly = true
),提高运行的效率。他的默认值为false。
11.5、超时属性
当前的事务访问数据时,有可能访问的数据被别的事务进行加锁处理,那么此时本事务就需要进行等待。超时属性指定了事务等待的最长时间,这个时间是以秒为单位的。他的默认值是-1,他最终的时间由对应的数据库来决定。
应用示范:@Transaction(timeout=秒数)
;
11.6、异常属性
Spring事务处理过程中,默认对RuntimeException及其子类采用的是回滚策略,而对于Exception及其子类采用的是提交策略。
// 异常属性有两个值
// 1. rollbackFor();表示回滚的异常类型,里面写异常的类型的字节码对象,他里面的值的类型是数组类型,所以可以写多个异常类型的字节码对象,用逗号隔开
rollbackFor({java.lang.Exception.class});
// noRollbackFor();表示不会滚的异常类型的字节码对象
noRollbackFor({java.lang.RuntimeException.class})
11.7、事务属性及其常见配置总结
-
隔离属性:一般用默认值。
-
传播属性:一般增删改用Required(默认值),查询操作用Supports。
-
只读属性:一般增删改设置readOnly的值为false,查询设置readOnly的值为true。
-
超时属性:一般用默认值为-1。
-
异常属性:一般用默认值。
总结: -
增删改操作:
@Transactional
。 -
查询操作:
@Transactional(propagation=Propagation.SUPPORTS,readOnly=true)
- 点赞
- 收藏
- 关注作者
评论(0)