Transaction rolled back because it has been marked as rollback-only问题解决
1、背景
在我们的日常开发中,经常会存在在一个Service层中调用另外一个Service层的方法。比如:我们有一个TaskService,里面有一个execTask方法,且这个方法存在事务,这个方法在执行完之后,需要调用LogService的insertLog方法记录一条日志,这个方法上也有事务,不管日志记录成功还是失败,都不能影响execTask方法的执行。因此我们很容易写出如下代码。
@Transactional
public void execTaskV1(){
log.info("开始执行任务");
try {
logService.insertLogV1();
} catch (Exception e) {
log.error("添加日志出现错误");
}
log.info("完成任务执行");
}
思考: 上方的代码,如果insertLogV1跑出了异常,execTaskV1方法的事务可以正常提交吗?
2、异常是如何实现出现的
1、了解Spring事务的传播属性
| 传播行为 | 描述 | 应用场景 | 行为特点 |
|---|---|---|---|
Propagation.REQUIRED |
如果当前存在事务,则加入该事务;如果当前没有事务,则启动一个新的事务。 | 大多数场景,如多个方法需要在同一个事务中完成。 | - 如果当前事务存在,方法执行在当前事务上下文中。 - 如果当前事务不存在,创建新事务。 |
Propagation.SUPPORTS |
如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。 | 对事务支持没有强制要求的场景,如只读查询。 | - 如果当前事务存在,方法执行在当前事务上下文中。 - 如果当前事务不存在,以非事务方式执行。 |
Propagation.MANDATORY |
如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。 | 必须在一个已存在的事务中执行的场景。 | - 必须在已有事务中执行,否则抛出 IllegalTransactionStateException。 |
Propagation.REQUIRES_NEW |
每次调用该方法时都会启动一个新的事务。当前事务(如果有)会被挂起。 | 需要独立事务的场景,如日志记录或独立的业务操作。 | - 总是创建新事务。 - 当前事务(如果有)会被挂起,直到新事务完成。 |
Propagation.NOT_SUPPORTED |
总是以非事务方式执行,并且暂停当前事务(如果有)。 | 不需要事务的场景,如简单的查询操作。 | - 总是以非事务方式执行。 - 暂停当前事务(如果有)。 |
Propagation.NEVER |
总是以非事务方式执行,如果当前存在事务,则抛出异常。 | 严格禁止事务的场景,如某些非事务性操作。 | - 必须在非事务上下文中执行,否则抛出 TransactionException。 |
Propagation.NESTED |
如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则启动一个新的事务。 | 需要嵌套事务的场景,如复杂的业务流程中需要独立的回滚点。 | - 如果当前事务存在,创建一个嵌套事务(依赖于数据库支持)。 - 如果当前事务不存在,创建新事务。 |
2、模拟异常出现
Transaction rolled back because it has been marked as rollback-only 这个异常在上述的案例中是如何实现的呢?
从上图中可知,出现了Transaction rolled back because it has been marked as rollback-only这个异常,那么这个异常是如何出现的呢?
其实这个是和Spring事务的传播属性Propagation有关。
默认情况下@Transaction的传播属性是Propagation.REQUIRED, 即如果当前存在事务,则加入该事务;如果当前没有事务,则启动一个新的事务。 在我们的例子中,事务的隔离级别都是Propagation.REQUIRED,即是在同一个事务中,因此insertLogV1方法抛出异常后,虽然上层捕获到了,但其实这个时候这个事务已经被标记成回滚状态了,因此事务无法提交成功。
如何解决: 只需要修改insertLogV1事务的传播属性为Propagation.REQUIRES_NEW即可。
3、完整代码
完整代码-https://gitee.com/huan1993/spring-cloud-parent/tree/master/springboot/springboot-transaction-v1
Transaction rolled back because it has been marked as rollback-only问题解决的更多相关文章
- “Transaction rolled back because it has been marked as rollback-only”
spring的声明事务提供了强大功能,让我们把业务关注和非业务关注的东西又分离开了.好东西的使用,总是需要有代价的.使用声明事务的时候,一 个不小心经常会碰到“Transaction rolled b ...
- Transaction rolled back because it has been marked as rollback-only
出现这种错误的原因 1.接口A 调用了接口B 2.接口B报异常了,没有在B里面进行try catch捕获 3.接口A对 接口B进行了try catch捕获 因为接口B报异常 会把当前事物A接口的事物( ...
- 【Spring】21、用spring目标对象处理Transaction rolled back because it has been marked as rollback-only
在使用spring做事务管理时,很多人都会遇到这样一段异常: org.springframework.transaction.UnexpectedRollbackException: Transact ...
- Transaction rolled back because it has been marked as rollback-only分析解决方法
1. Transaction rolled back because it has been marked as rollback-only事务已回滚,因为它被标记成了只回滚<prop key= ...
- 【springcloud】Transaction rolled back because it has been marked as rollback-only
问题: 一个ajax请求,发生系统错误,错误内容:Transaction rolled back because it has been marked as rollback-only 原因是调用的s ...
- [转]Spring事务嵌套引发的血案---Transaction rolled back because it has been marked as rollback-only
原文地址:https://blog.csdn.net/f641385712/article/details/80445912 1.概述 想必大家一想到事务,就想到ACID,或者也会想到CAP.但笔者今 ...
- @Transactional事务回滚异常:Transaction rolled back because it has been marked as rollback-only
问题描述 事务设置手动回滚:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly() 代码需要返回比较友好的提示,但t ...
- Transaction rolled back because it has been marked as rollback-only 原因 和解决方案
产生原因 , 1 serviceA 调用 serviceB 然后 B 抛出异常 ,B 所在的 事物 回滚,B 把当前可写 事物标记成 只读事物 , 2 如果 A 和B 是在 同一个事物环境,并且 ...
- Spring事务嵌套引发的问题--Transaction rolled back because it has been marked as rollback-only
转载https://blog.csdn.net/f641385712/article/details/80445912 读了两边才找到问题
- 记一次org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only异常
@Transactional(rollbackFor = Exception.class) @Overridepublic DubboResult<Boolean> productAddO ...
随机推荐
- Mybatis【7】-- Mybatis如何知道增删改是否成功执行?
代码直接放在Github仓库[https://github.com/Damaer/Mybatis-Learning/tree/master/mybatis-05-CURD ] 需要声明的是:此Myba ...
- 【kernel】从 /proc/sys/net/ipv4/ip_forward 参数看如何玩转 procfs 内核参数
本文的开篇,我们先从 sysctl 这个命令开始. sysctl 使用 sysctl 是一个 Linux 系统工具,后台实际上是 syscall,它允许用户查看和动态修改内核参数. # 查看当前设置的 ...
- C#中使用IMemoryCache实现内存缓存
1 缓存基础知识 缓存是实际工作中非常常用的一种提高性能的方法. 缓存可以减少生成内容所需的工作,从而显著提高应用程序的性能和可伸缩性. 缓存最适用于不经常更改的数据. 通过缓存,可以比从原始数据源返 ...
- github访问不了解决方法
github突然无法访问,解决办法如下-迷恋自留地 首先通过网址https://tool.chinaz.com/dns?type=a&host=github.com 修改hosts文件,win ...
- 对DenseTensor进行Transpose
ML.NET 是微软推出的为. NET 平台设计的深度学习库,通过这个东西(ModelBuilder)可以自己构建模型,并用于后来的推理与数据处理.虽然设计是很好的,但是由于现在的 AI 发展基本上都 ...
- 利用shell中awk和xargs以及sed将多行多列文本中某一列合并成一行
一.问题描述最近需要利用Shell将多行多列文本中某一列,通过指定的分隔符合并成一行.假设需要处理的文本如下: 我们主要处理的是,将用户名提取处理,合并成一行,并通过逗号进行分隔.最终的格式如下: & ...
- gitlab16 gitlab-runner
gitlab-runner verify --delete FederatedKMeansSecureModelInference gitlab-runner register --url http ...
- shell 读取文件内容到数组
在 shell 脚本中,可以使用下面的语法来读取文件内容并将其存储到数组中: bash 复制代码 array=() while read line; do array+=("$line& ...
- 龙哥收集的Github资源——Python量化不要自己造轮子
打开github后,在搜索框中输入下面的项目作者及项目名称,然后点一下 All Github 搜索 格式 user:xxxxx in:name xxxxxxxxxxxxx 举例 user:Cken ...
- Qt/C++推流程序自动生成网页远程查看实时视频流(视频文件/视频流/摄像头/桌面转成流媒体rtmp+hls+webrtc)
一.前言说明 推流程序将视频流推送到流媒体服务器后,此时就等待验证拉流播放,一般可以选择ffplay命令行播放或者vlc等播放器打开播放,也可以选择网页直接打开拉流地址播放,一般主流的浏览器都支持网页 ...