环境:Spring5.3.23
Spring事务超时是指一个事务在执行中最长的允许时间 。如果事务在超时时间内未能完成,则会自动回滚 。超时时间可以通过设置来控制,以确保事务在规定的时间内完成或回滚,避免数据一致性问题 。
在工作中你有配置事务的超时时间吗?如何进行配置事务超时时间?
1. 配置事务超时时间注解方式:
// 这里单位是s@Transactional(timeout = 2)public void save() {}
编程方式1:
@Resourceprivate PlatformTransactionManager tm ;DefaultTransactionDefinition definition = new DefaultTransactionDefinition();definition.setTimeout(2) ;
编程方式2:
@Resourceprivate PlatformTransactionManager tm ;public void update() {TransactionTemplate template = new TransactionTemplate(tm) ;template.setTimeout(2) ;template.execute(new TransactionCallback<Object>() {@Overridepublic Object doInTransaction(TransactionStatus status) {// ...return null ;}}) ;}
以上3种方式读可以进行事务超时的设置 , 什么情况下才能算是事务超时呢?
2. 准备环境准备一张2000w数据的表
文章插图
图片
表字段信息如下:
文章插图
图片
此表除主键外没有任何的索引 。
文章插图
图片
3. 模拟事务超时
- 测试1
// 将超时时间设置为20s@Transactional(timeout = 20)public void query() {long start = System.currentTimeMillis() ;jdbcTemplate.execute("select count(*) from p_user") ;System.out.println("耗时:" + (System.currentTimeMillis() - start) + "毫秒") ;}
执行结果:耗时:3198毫秒
接下来将超时时间改成3s执行结果如下:
13:56:01.425 [mAIn] WARNc.zaxxer.hikari.pool.ProxyConnection - HikariPool-1 - Connection com.MySQL.cj.jdbc.ConnectionImpl@504ecd marked as broken because of SQLSTATE(null), ErrorCode(0)com.mysql.cj.jdbc.exceptions.MySQLTimeoutException: Statement cancelled due to timeout or client requestat com.mysql.cj.jdbc.exceptions.SQLExceptionsMApping.translateException(SQLExceptionsMapping.JAVA:113)at com.mysql.cj.jdbc.StatementImpl.checkCancelTimeout(StatementImpl.java:2167)
从异常信息看到抛出了超时异常 。这里的超时是sql执行的超时,是由我们的驱动程序抛出的异常 。- 测试2
@Transactional(timeout = 2)public void query() {long start = System.currentTimeMillis() ;try {TimeUnit.SECONDS.sleep(3) ;} catch (InterruptedException e) {e.printStackTrace();}// 执行非常简单的操作jdbcTemplate.execute("select 1") ;System.out.println("耗时:" + (System.currentTimeMillis() - start) + "毫秒") ;}
执行结果:14:08:44.000 [main] DEBUG o.s.jdbc.core.JdbcTemplate - Executing SQL statement [select 1]Exception in thread "main" org.springframework.transaction.TransactionTimedOutException: Transaction timed out: deadline was Wed Oct 11 14:08:42 CST 2023at org.springframework.transaction.support.ResourceHolderSupport.checkTransactionTimeout(ResourceHolderSupport.java:155)
抛出了超时异常,而这个异常是由Spring框架抛出的 。- 测试3
@Transactional(timeout = 2)public void query() {long start = System.currentTimeMillis() ;jdbcTemplate.execute("select 1") ;try {TimeUnit.SECONDS.sleep(3) ;} catch (InterruptedException e) {e.printStackTrace();}System.out.println("耗时:" + (System.currentTimeMillis() - start) + "毫秒") ;}
执行结果:耗时:3015毫秒
程序正常运行- 测试4
@Transactional(timeout = 2)public void query() {long start = System.currentTimeMillis() ;jdbcTemplate.execute("select 1") ;try {TimeUnit.SECONDS.sleep(3) ;} catch (InterruptedException e) {e.printStackTrace();}System.out.println("耗时:" + (System.currentTimeMillis() - start) + "毫秒") ;// 再次执行数据库相关操作jdbcTemplate.execute("select 1") ;}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Spring Cloud微服务架构:构建弹性和可伸缩的云原生应用
- Spring 如何解决循环依赖?
- 三个要点,掌握Spring Boot单元测试
- CORS 跨域资源共享在Spring Boot中的实现
- Java面试题之SpringBoot 框架
- SpringBoot中ApplicationEvent详解
- 一文读懂Spring框架中的不同类型事件
- SpringBoot 并发编程学习历程
- MySQL 事务死锁问题排查
- 在SpringBoot中通过Canal实现MySQL与Redis的数据同步