spring事务属性的几个试验

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介:
首先我们知道,spring的事务管理有以下几种事务属性:
PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
 PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
 PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
 PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
 PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
 PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
 PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED 类似的操作。


=======================
针对这些事务属性,我做了几次试验。
使用的代码简单描述就是:
外层方法{

try{内层方法();}catchRuntimeException e{}
}

内层方法(){
抛出 RuntimeException 
}

=======================
REQUIRED的试验时,配置是:
<tx:method name="外层方法" propagation="REQUIRED" />
<tx:method name="内层方法" propagation="REQUIRED" />
在日志中看到:
1、为外层方法创建事务

- Creating new transaction with name [外层方 法]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT

2、为内层方法配置事务

 - Participating in existing transaction

可以看到 ,内层方法使用的是外层方法的事务上下文。然后,当内层方法抛出异常时,日志中记录:

Setting JDBC transaction [...] rollback-only
即要求该事务回滚。但是内层方法的异常被外层方法捕获并处理了, 外层方法仍然会继续执行,并在执行完毕后提交事务。这时日志中记录并抛出异常:

Global transaction is marked as rollback-only but transactional code requested commit

(执行事务回滚...

org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only


 

所谓 支持当前事务 就是在当前事务的上下文内执行目标方法。 内层方法对事务的操作会影响到外层方法。

=========================

NESTED 的试验时,配置如下:

<tx:method name="外层方法" propagation="REQUIRED" />
<tx:method name="内层方法" propagation="NESTED" />

在日志中看到:

1、为外层方法创建事务

- Creating new transaction with name [外层方 法]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT

2、为内层方法创建嵌套事务

-  Creating nested transaction with name [ 内层方法 ]

1、 内层方法回滚、提交

 - Rolling back transaction to savepoint

2、 外层方法继续执行并提交

外层方法逻辑输出

- Triggering beforeCommit synchronization

……
 

可见,嵌套事务与当前事务可以认为是两个事务,只是它不会挂起当前事务。嵌套事务即使回滚,当前事务仍然可以正常提交。

=======================

SUPPORTS试验时, 使用的配置是:

<tx:method name="外层方法" propagation="SUPPORTS" />
<tx:method name="内层方法" propagation=" REQUIRED " />

另外内层方法改为了:

内层方法(){
return
}
这种方案下,日志中只有为内层方法创建事务的记录,对外层方法基本是“不闻不问”的。而如果把配置反过来,改成

<tx:method name="外层方法" propagation=" REQUIRED " />
<tx:method name="内层方法" propagation="SUPPORTS" />

那么, spring会为外层方法创建事务,而对内存方法则使用外层方法的事务上下文。

但是,如果配置为:

<tx:method name="外层方法" propagation="SUPPORTS" />
<tx:method name="内层方法" propagation="SUPPORTS" />

日志中会出现几行这样的记录:

Triggering beforeCommit synchronization

Triggering beforeCompletion synchronization

Triggering afterCommit synchronization

Triggering afterCompletion synchronization

这些是事务提交前后的日志;但是却找不到创建事务相关的日志。我不清楚为什么会出现这种事务前后行为不匹配的情况。以后再琢磨琢磨吧。

======================

其它的几种情况我没有再测试了。不过,事务相关配置的基本含义到这里差不多已经清楚了,其它的情况可以“同理可证”或者“由此推知”了吧。


本文转自 斯然在天边 51CTO博客,原文链接:http://blog.51cto.com/winters1224/807500,如需转载请自行联系原作者
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
Spring中事务失效的场景
因为Spring事务是基于代理来实现的,所以某个加了@Transactional的⽅法只有是被代理对象调⽤时, 那么这个注解才会⽣效 , 如果使用的是被代理对象调用, 那么@Transactional会失效 同时如果某个⽅法是private的,那么@Transactional也会失效,因为底层cglib是基于⽗⼦类来实现 的,⼦类是不能重载⽗类的private⽅法的,所以⽆法很好的利⽤代理,也会导致@Transactianal失效 如果在业务中对异常进行了捕获处理 , 出现异常后Spring框架无法感知到异常, @Transactional也会失效
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——常见问题总结
本文总结了Spring Boot中使用事务的常见问题,虽然通过`@Transactional`注解可以轻松实现事务管理,但在实际项目中仍有许多潜在坑点。文章详细分析了三个典型问题:1) 异常未被捕获导致事务未回滚,需明确指定`rollbackFor`属性;2) 异常被try-catch“吃掉”,应避免在事务方法中直接处理异常;3) 事务范围与锁范围不一致引发并发问题,建议调整锁策略以覆盖事务范围。这些问题看似简单,但一旦发生,排查难度较大,因此开发时需格外留意。最后,文章提供了课程源代码下载地址,供读者实践参考。
31 0
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——Spring Boot 事务配置
本文介绍了 Spring Boot 中的事务配置与使用方法。首先需要导入 MySQL 依赖,Spring Boot 会自动注入 `DataSourceTransactionManager`,无需额外配置即可通过 `@Transactional` 注解实现事务管理。接着通过创建一个用户插入功能的示例,展示了如何在 Service 层手动抛出异常以测试事务回滚机制。测试结果表明,数据库中未新增记录,证明事务已成功回滚。此过程简单高效,适合日常开发需求。
39 0
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——事务相关
本文介绍Spring Boot事务配置管理,阐述事务在企业应用开发中的重要性。事务确保数据操作可靠,任一异常均可回滚至初始状态,如转账、购票等场景需全流程执行成功才算完成。同时,事务管理在Spring Boot的service层广泛应用,但根据实际需求也可能存在无需事务的情况,例如独立数据插入操作。
19 0
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——少量配置信息的情形
本课主要讲解Spring Boot项目中的属性配置方法。在实际开发中,测试与生产环境的配置往往不同,因此不应将配置信息硬编码在代码中,而应使用配置文件管理,如`application.yml`。例如,在微服务架构下,可通过配置文件设置调用其他服务的地址(如订单服务端口8002),并利用`@Value`注解在代码中读取这些配置值。这种方式使项目更灵活,便于后续修改和维护。
18 0
Spring中的事务是如何实现的
1. Spring事务底层是基于数据库事务和AOP机制的 2. ⾸先对于使⽤了@Transactional注解的Bean,Spring会创建⼀个代理对象作为Bean 3. 当调⽤代理对象的⽅法时,会先判断该⽅法上是否加了@Transactional注解 4. 如果加了,那么则利⽤事务管理器创建⼀个数据库连接 5. 并且修改数据库连接的autocommit属性为false,禁⽌此连接的⾃动提交,这是实现Spring事务⾮ 常重要的⼀步 6. 然后执⾏当前⽅法,⽅法中会执⾏sql 7. 执⾏完当前⽅法后,如果没有出现异常就直接提交事务 8. 如果出现了异常,并且这个异常是需要回滚的就会回滚事务
Spring事务失效,常见的情况有哪些?
本文总结了Spring事务失效的7种常见情况,包括未启用事务管理功能、方法非public类型、数据源未配置事务管理器、自身调用问题、异常类型错误、异常被吞以及业务和事务代码不在同一线程中。同时提供了两种快速定位事务相关Bug的方法:通过查看日志(设置为debug模式)或调试代码(在TransactionInterceptor的invoke方法中设置断点)。文章帮助开发者更好地理解和解决Spring事务中的问题。
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——指定项目配置文件
在实际项目中,开发环境和生产环境的配置往往不同。为简化配置切换,可通过创建 `application-dev.yml` 和 `application-pro.yml` 分别管理开发与生产环境配置,如设置不同端口(8001/8002)。在 `application.yml` 中使用 `spring.profiles.active` 指定加载的配置文件,实现环境快速切换。本节还介绍了通过配置类读取参数的方法,适用于微服务场景,提升代码可维护性。课程源码可从 [Gitee](https://gitee.com/eson15/springboot_study) 下载。
33 0
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——少量配置信息的情形
在微服务架构中,随着业务复杂度增加,项目可能需要调用多个微服务。为避免使用`@Value`注解逐一引入配置的繁琐,可通过定义配置类(如`MicroServiceUrl`)并结合`@ConfigurationProperties`注解实现批量管理。此方法需在配置文件中设置微服务地址(如订单、用户、购物车服务),并通过`@Component`将配置类纳入Spring容器。最后,在Controller中通过`@Resource`注入配置类即可便捷使用,提升代码可维护性。
20 0
【SpringFramework】Spring事务
本文简述Spring中数据库及事务相关衍伸知识点。
57 9

热门文章

最新文章