https://blog.csdn.net/yalishadaa/article/details/70261973
当同一个应用程序或者不同应用程序中的多个事务在同一个数据集上并发执行时,可能会出现许多意外的问题
并发事务所导致的问题可以分为下面三种类型
:
脏读:
对于两个事物
T1,T2, T1
读取了已经被
T2
更新但还没有被提交的字段
.
之后
,
若
T2
回滚
,T1
读取的内容就是临时且无效的
.
不可重复读:
对于两个事物
T1,T2, T1
读取了一个字段
,
然后
T2
更新了该字段
.
之后
,T1
再次读取同一个字段
,
值就不同了
.
幻读:
对于两个事物
T1,T2, T1
从一个表中读取了一个字段
,
然后
T2
在该表中插入了一些新的行
.
之后
,
如果
T1
再次读取同一个表
,
就会多出几行
.
从理论上来说
,
事务应该彼此完全隔离
,
以避免并发事务所导致的问题
.
然而
,
那样会对性能产生极大的影响
,
因为事务必须按顺序运行
.
在实际开发中
,
为了提升性能
,
事务会以较低的隔离级别运行
.
事务的隔离级别可以通过隔离事务属性指定
事务的隔离级别要得到底层数据库引擎的支持
,
而不是应用程序或者框架的支持
.
Oracle
支持的
2
种事务隔离级别:
READ_COMMITED, SERIALIZABLE
Mysql
支持
4
中事务隔离级别
.
事务的回滚通过
@Transactional
注解完成。
1.设置事务的隔离级别:
可以在
@Transactional
的
isolation
属性中设置隔离级别.
2.设置事务的回滚属性
默认情况下只有未检查异常(RuntimeException和Error类型的异常)会导致事务回滚.而受检查异常不会.
事务的回滚规则可以通过@Transactional注解的rollbackFor和noRollbackFor属性来定义.
ex:
- @Transactional(propagation = Propagation.REQUIRES_NEW,isolation = Isolation.READ_COMMITTED,
- noRollbackFor = {UserAccountException.class},
- )
- UserAccountException
- rollbackFor: 遇到时必须进行回滚
- noRollbackFor: 一组异常类,遇到时必须不回滚
超时事务属性: 事务在强制回滚之前可以保持多久.这样可以防止长期运行的事务占用资源.
ex:
- @Transactional(propagation = Propagation.REQUIRES_NEW,isolation = Isolation.READ_COMMITTED,
- noRollbackFor = {UserAccountException.class},
- timeout = 3)
4. 设置只读事务属性
表示这个事务只读取数据但不更新数据
,
这样可以帮助数据库引擎优化事务
.
ex:
- @Transactional(propagation = Propagation.REQUIRES_NEW,isolation = Isolation.READ_COMMITTED,
- noRollbackFor = {UserAccountException.class},
- readOnly = false,timeout = 1)