关于Spring事务超时时间的实现,一直都没太弄清楚,终于在看到一篇事务超时文章后,通过测试用例证明通常情况下@Transactional中配置的timeout都是无效的。

首先说明下测试的注意事项,就是除了@Transactional的timeout配置外,不要配置其他超时时间,比如mybatis xml中sql的timeout,jdbc properties中的socket timeout(connectionTimeout和socketTimeout)以及mysql的innodb_lock_wait_timeout(默认50s)。

测试方法如下,超时时间为1s,线程中等待3s,使用Mybatis方式配置sql

@Transactional(timeout=1)
public void batchUpdate(){try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}int updateRow = userMapper.batchUpdate(userList);System.out.println("updateRow:" + updateRow);
}

测试结果,事务执行成功了,第一次测试的时候,我也是惊呆了。什么鬼??项目里配置的timeout竟然都是摆设。

再来测试JdbcTemplate直接执行sql的方法

public class UserJdbcTemplateMapper {private JdbcTemplate jdbcTemplate;public int updateUser(){return jdbcTemplate.update("update user set age = 10 where id = 1");}
}

@Transactional还是上面的配置,测试结果为

org.springframework.transaction.TransactionTimedOutException: Transaction timed out: deadline was Fri Feb 02 20:48:43 CST 2018

建议大家自己测试一下,亲自体验的感觉特别好。下面根据DataSourceTransactionManager来分析其原理。

抽象AbstractPlatformTransactionManager对@Transactional的超时时间没有任何处理,而在DataSourceTransactionManager的doBegin方法中将其设置到ConnectionHolder中。

if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}

实际上就是设置了一个deadline

public void setTimeoutInSeconds(int seconds) {setTimeoutInMillis(seconds * 1000);
}public void setTimeoutInMillis(long millis) {this.deadline = new Date(System.currentTimeMillis() + millis);
}

而对deadline的校验的方法就是checkTransactionTimeout,在获取超时时间的方法里被执行

// 获取剩余时间(单位为秒)
public int getTimeToLiveInSeconds() {double diff = ((double) getTimeToLiveInMillis()) / 1000;int secs = (int) Math.ceil(diff);checkTransactionTimeout(secs <= 0);return secs;
}// 获取剩余时间(单位为毫秒)
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;
}// 校验是否超时,抛出TransactionTimedOutException异常
private void checkTransactionTimeout(boolean deadlineReached) throws TransactionTimedOutException {if (deadlineReached) {setRollbackOnly();throw new TransactionTimedOutException("Transaction timed out: deadline was " + this.deadline);}
}

而对获取剩余时间方法的调用为DataSourceUtils的applyTimeout,将超时时间转换为JDBC的Statement的queryTimeout,因而Spring事务的超时时间也就是通过Statement的超时来实现。

public static void applyTimeout(Statement stmt, @Nullable DataSource dataSource, int timeout) throws SQLException {Assert.notNull(stmt, "No Statement specified");ConnectionHolder holder = null;if (dataSource != null) {holder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);}if (holder != null && holder.hasTimeout()) {// Remaining transaction timeout overrides specified value.stmt.setQueryTimeout(holder.getTimeToLiveInSeconds());}else if (timeout >= 0) {// No current transaction timeout -> apply specified value.stmt.setQueryTimeout(timeout);}
}

可是applyTimeout的调用者只有JdbcTemplate和TransactionAwareDataSourceProxy。在JdbcTemplate的execute方法中通过applyStatementSettings方法设置了超时时间。而TransactionAwareDataSourceProxy则是JDK代理的InvocationHandler的实现类,感觉应该是DataSource的代理类。但是纵观Spring事务管理的核心实现方法中获取DataSource的操作,都没有对原始DataSource进行代理的操作,甚至在DataSourceTransactionManager的setDataSource方法中,判断如果DataSource为TransactionAwareDataSourceProxy类型,则获取其原始DataSource。

public void setDataSource(@Nullable DataSource dataSource) {if (dataSource instanceof TransactionAwareDataSourceProxy) {this.dataSource = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource();}else {this.dataSource = dataSource;}
}

因此就算在xml中配置了TransactionAwareDataSourceProxy来代理原始DataSource,对于DataSourceTransactionManager来说,只是虚设。

<bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"><constructor-arg index="0" ref="basicDataSource"></constructor-arg>
</bean>

因此对于Spring事务超时时间的设置,要格外的注意,可以参考事务超时这篇文章,对各层的超时时间的介绍及作用相当清楚。

Spring事务管理-超时时间相关推荐

  1. Spring事务管理 与 SpringAOP

    1,Spring事务的核心接口 Spring事务管理的实现有许多细节,如果对整个接口框架有个大体了解会非常有利于我们理解事务,下面通过讲解Spring的事务接口来了解Spring实现事务的具体策略.  ...

  2. 什么是事务的传播_这么漂亮的Spring事务管理详解,你不来看看?

    事务概念回顾 什么是事务? 事务是逻辑上的一组操作,要么都执行,要么都不执行. 事物的特性(ACID): 原子性: 事务是最小的执行单位,不允许分割.事务的原子性确保动作要么全部完成,要么完全不起作用 ...

  3. Spring事务管理(详解+实例)

    写这篇博客之前我首先读了<Spring in action>,之后在网上看了一些关于Spring事务管理的文章,感觉都没有讲全,这里就将书上的和网上关于事务的知识总结一下,参考的文章如下: ...

  4. 多数据源 事务管理_可能是最漂亮的Spring事务管理详解

    事务概念回顾 什么是事务? 事务是逻辑上的一组操作,要么都执行,要么都不执行. 事物的特性(ACID): 原子性: 事务是最小的执行单位,不允许分割.事务的原子性确保动作要么全部完成,要么完全不起作用 ...

  5. spring事务管理一:关于事务管理的接口

    2019独角兽企业重金招聘Python工程师标准>>> spring事务管理主要有三个接口: 事务管理器接口:PlatformTransactionManager.可以为不同的框架提 ...

  6. Spring事务管理机制

    Spring事务管理的四个优点: 提供一致的对于不同的事务管理的API 支持声明式事务管理(重点) 编程事务管理(在开发中应用比较少) 优秀的整合与Spring的数据访问 我们重点讲解spring的事 ...

  7. Spring事务管理(三)-PlatformmTransactionManager解析和事务传播方式原理

    2019独角兽企业重金招聘Python工程师标准>>> Spring在事务管理时,对事务的处理做了极致的抽象,即PlatformTransactionManager.对事务的操作,简 ...

  8. Spring事务管理接口

    Spring 的事务管理是基于 AOP 实现的,而 AOP 是以方法为单位的.Spring 的事务属性分别为传播行为.隔离级别.只读和超时属性,这些属性提供了事务应用的方法和描述策略. 在 Java ...

  9. Spring事务管理全面分析

    Spring 事务属性分析 什么是事物   事务管理对于企业应用而言至关重要.它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性.就像银行的自助取款机,通常都能 ...

最新文章

  1. 没有顶会的CV/NLP方向的博士生毕业出路在哪里?
  2. NumPy迎来重大版本更新,新增函数注释、滑动窗口视图功能,仅支持Python 3.7以上版本...
  3. 获香港证监会颁发牌照的弘量研究,正用智能投顾帮助金融机构降低成本,提升资产管理能力 By 藤子2017年10月09日 17:16 撰文 | 藤子 2015 年,雷春然和黄耀东都是在香港科技大学的
  4. CSS3学习——设计优雅的数据表格
  5. arm 交叉编译找不到so_嵌入式杂谈之交叉编译
  6. ps法线贴图插件_法线与置换贴图原理讲解以及烘焙制作!
  7. jQuery表单插件ajaxForm,ajaxSubmit使用详解
  8. 线性空间与坐标空间的同构
  9. Introduction to Computer Networking学习笔记(九):error detection 错误探查 Checksum、CRC、MAC
  10. wps中打印图片去除黑边
  11. 高德地图获取经纬度坐标
  12. 计算机网页外文文献图书,免费外文文献网站.doc
  13. 软件开发阶段及其文档简述
  14. 让 Linux 更安全
  15. 关于硕士毕业直接工作还是继续读博的一些思考
  16. 网易明日之后那个服务器人最多,明日之后:网易“公认”全服前4强营地出炉,竟全部来自一个区...
  17. controllerAs
  18. R语言自学笔记:数据处理、数据分布及数据检验
  19. EMS是中国邮政提供的一种快递服务。
  20. 我来玩转一下arp -a (pc ping 手机)

热门文章

  1. ubuntu 16.04 通过手机蓝牙上网
  2. 中小型局域网组网方案的设计和规划(用PT模拟实验环境)
  3. 2021年,7个性价比最高的CSS特性值得一试
  4. 苹果手机关闭自动更新_如果你用苹果手机,记得关闭这3个按钮,手机还再用4年...
  5. 【Linux】Linux的信号
  6. 【Linux】一篇文章搞定 进程间通信 之 信号机制
  7. 游戏行业实战案例5:玩家在线分布
  8. 背后的力量 | 推动政府数字化建设 华云数据为潜江市生态环境局搭建新一代企业级云平台
  9. 作为前端,我对业务的一点理解
  10. vue.js 密码加密_密码学初探:隐藏信息的艺术——区块链技术引卷之十一