Spring事务回滚核心源码解读

news/2025/3/16 16:10:33/

记一次Springboot事务超时不回滚的分析过程

在Springboot中,我用的xml进行事务管理,DataSourceTransactionManager作为事务管理器,配置了事务控制在Service层;在事务管理器中,配置了defaultTimeout事务超时时间为5秒,开始的认知里,如果事务执行超过5秒,Service层未执行完成,则认为会回滚事务
事务管理器的配置如下

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/><property name="defaultTimeout" value="5"/></bean>

事务控制在Service层配置

<aop:config><aop:pointcut id="txPointcut" expression="execution(* com.miso.infrastructure.asynctask.service.*.*(..))" /><aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/></aop:config>

开始测试

我的测试程序执行顺序是这样的:Controller->ServiceA->ServiceB->Dao
从Controller调用ServiceA开始,到ServiceA执行结束,是一个事务控制生命周期,如果在这个生命周期里,执行的时长超过事务管理器中配置的时间5秒,则事务回滚
在这里插入图片描述
为了能模拟延迟的效果,我在ServiceB调用Dao之前和之后,分别增加了Sleep的效果,让程序睡10秒
场景一:在调用Dao之前,增加让程序睡10秒

java">    public AsyncTaskEntity createAsyncTask(AsyncTaskEntity asyncTaskEntity) {Thread.sleep(10000);asyncTaskDao.createAsyncTask(asyncTaskEntity);return asyncTaskEntity;}

场景二:在调用Dao之后,增加让程序睡10秒

java">    public AsyncTaskEntity createAsyncTask(AsyncTaskEntity asyncTaskEntity) {asyncTaskDao.createAsyncTask(asyncTaskEntity);Thread.sleep(10000);return asyncTaskEntity;}

在我的第一认知里面,不管是场景一还是场景二,这两种都应该是超时回滚的,但实际测试结果出呼我所料,第一种场景事务回滚,而第二种场景没有回滚,第二种场景的即使超过了超时时间5秒,但是事务依然是提交的,在数据库中可以看到有新增的记录,是不是很意外,为什么事务执行时间超过了5秒,事务没有回滚,而是提交成功了呢?

开始分析

从这个报错的信息中,我们可以看到有一个抽象类ResourceHolderSupport,里面有个checkTransactionTimeout方法,这个方法里面扫了一个事务超时的异常
在这里插入图片描述
ResourceHolderSupport.checkTransactionTimeout源码如下,如果deadlineReached为true,则执行事务回滚,并抛事务超时异常

java">	private void checkTransactionTimeout(boolean deadlineReached) throws TransactionTimedOutException {if (deadlineReached) {setRollbackOnly();throw new TransactionTimedOutException("Transaction timed out: deadline was " + this.deadline);}}

从堆栈中可以看到,调用checkTransactionTimeout方法的是getTimeToLiveInMillis方法,ResourceHolderSupport.getTimeToLiveInMillis源码如下

java">	public long getTimeToLiveInMillis() throws TransactionTimedOutException{if (this.deadline == null) {throw new IllegalStateException("No timeout specified for this resource holder");}long timeToLive = this.deadline.getTime() - System.currentTimeMillis();checkTransactionTimeout(timeToLive <= 0);return timeToLive;}

从源码中可以看到,deadline的时间减去当前系统时间,如果小于0,则deadlineReached为true,事务进行回滚

那什么时候会调用ResourceHolderSupport.getTimeToLiveInMillis方法呢,从堆栈中可以看到整个的调用链如下:
在这里插入图片描述
在执行SimpleExecutor.prepareStatement方法时,会从Spring事务管理器中获取超时时间,最终调用到ResourceHolderSupport.getTimeToLiveInMillis
在这里插入图片描述
从这个调用链可以看出,Spring是在调用Dao的时候,去判断事务超时时间的,如果执行时间超过事务超时时间,则执行回滚,并抛出TransactionTimedOutException异常

因此到这里就可以解释了为什么上面 场景二:在调用Dao之后,增加让程序睡10秒不会回滚,因为dao层已经执行完成,后面不会进行超时判断了,除非在后面有另一个DAO的操作(前提是:同一个事务)

这里还有一个问题,ResourceHolderSupport.getTimeToLiveInMillis中的deadline.getTime()这个时间是在什么时候设置上的呢,我们注意到在ResourceHolderSupport中有个setTimeoutInMillis方法,这里有设置deadline的值,源码如下
在这里插入图片描述

那什么时候调用setTimeoutInMillis方法呢,在方法里打判断,查看堆栈信息,发现如下调用链
在这里插入图片描述

从调用链可以看出,Controll调用ServiceA之前,Spring框架会调用事务管理器DataSourceTransactionManager的doBegin方法开启事务,并在方法里面调用ResourceHolderSupport.setTimeoutInSeconds方法设置超时时间,之后才调用到ServiceA

因此在Controller调用ServiceA之前,Spring框架就会开启事务,并设置事务超时时间


http://www.ppmy.cn/news/1441748.html

相关文章

可替代IBM DOORS的现代化需求管理解决方案Jama Connect,支持数据迁移及重构、实时可追溯性、简化合规流程

作为一家快速发展的全球性公司&#xff0c;dSPACE一直致力于寻找保持领先和优化开发流程的方法。为推进其全球现代化计划&#xff0c;dSPACE开始寻找可以取代传统需求管理平台&#xff08;IBM DOORS&#xff09;的需求管理解决方案。 通过本次案例&#xff0c;您将了解dSPACE为…

Mockito Mybatis-plus 单元测试

1. mock Mybatis-plus 自带 ServiceImpl方法问题 分析 mybatis-plus 自带的ServiceImpl&#xff0c;其实其最后执行使用的是我们所创建的Mapper&#xff0c;他最终会注入到 ServiceImpl的baseMapper中 - 示例 业务代码 // 实体 public class UtilSaleData { }// mapper public …

深度学习与目标检测:从卷积神经网络到YOLOv8概念介绍

深度学习与目标检测&#xff1a;从卷积神经网络到YOLOv8的深入探索 随着人工智能技术的迅猛发展&#xff0c;深度学习和计算机视觉领域取得了举世瞩目的成果。在目标检测这一关键任务中&#xff0c;卷积神经网络&#xff08;CNN&#xff09;和YOLO系列模型发挥着至关重要的作用…

uniapp:聊天消息列表(好友列表+私人单聊)支持App、H5、小程序

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 ⭐ 文章简介&#xff08;效果图展示&#xff…

centos7服务器系统如何安装宋体字文件

centos7服务器系统如何安装宋体字文件&#xff01; 最近开发的积德寺app,菩提佛堂祈福平台网站发布后&#xff0c;由于服务器之前遇到了攻击&#xff0c;数据丢失了&#xff0c;重新安装了一遍系统centos7.发现客户的功德证书创建后&#xff0c;字体乱码了。很明显是缺少了宋体…

MF(推荐系统的矩阵分解技术)论文笔记

论文概述 推荐系统的矩阵分解技术可以为用户提供更为准确的个性化推荐&#xff0c;对比传统的近邻技术&#xff0c;矩阵分解技术可以纳入更多信息&#xff0c;如隐式反馈、时间效应和置信度 近邻技术&#xff1a;基于用户或物品之间的相似性进行推荐&#xff0c;当用户之间已…

【MySQL】InnoDB与MyISAM存储引擎的区别与选择

存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式 。 存储引擎是基于表的&#xff0c;而不是基于库的&#xff0c;所以存储引擎也可被称为表类型。我们可以在创建表的时候&#xff0c;来指定选择的存储引擎&#xff0c;如果没有指定将自动选择默认的存储引擎。…

mysql 开启远程连接

登录到mysql mysql -uroot -p 打开mysql数据库并查询user表 use mysql; select user, host from user;更改需要远程连接数据库为任何ip 可以连接&#xff0c; 并刷新系统权限相关的表 update user set host% where hostlocalhost and userroot; flush privileges;