Spring 事务在实际项目中遇到的问题
2017-03-12 00:00
239 查看
PROPAGATION_REQUIRED : 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS : 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY : 支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW : 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED : 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER : 以非事务方式执行,如果当前存在事务,则抛出异常。
以上是Spring事务的传播行为,一般我们项目默认使用的是PROPAGATION_REQUIRED
如下图
1. 如果接口中方法需要语义化,那么可能会达不到基础项目默认配置的 声明式事务 申明的规则,从而没有被事务进行管理.
比如 : 购买XXX这个动作,buyXXX();如果声明式事务没有配置这项,那么需要自行加入配置
否则事务没管理到,会出现一些数据不一致的问题.
如果觉得麻烦,那么可以声明式事务和注解式一起使用,在方法上加入
注解即可
2. 事务传播行为的选择,根据业务场景选择不同的传播行为
这是我在一个计划任务处理时踩的坑
业务场景 :
每个月给用户赠送一定量的话费.
我的处理方式是 :
查询出当月所有需要赠送的记录,然后for循环调外部API进行赠送处理.
问题 :
1. 查询出当月所有需要赠送的记录(如果数据量日渐增大,那么一次全部查询出来,会造成java.lang.OutOfMemoryError)
2. 事务使用的是(PROPAGATION_REQUIRED默认事务),并且如果中间出现像SQL连接中断,数据库锁获取失败(有遇到过锁获取了40分钟还没有获取到,导致异常)等等,那么数据全部回滚.如果数据有1w条,中间已经处理了9999条,到最后一条数据处理失败了,数据回滚不说,任务还需要重来.
3. 调外部API进行赠送处理,外部只给了你充值的功能,并不会给你扣款,或者冲正的接口,如果中间出异常数据回滚了,那么只会回滚当前系统数据库的数据.
我后面修改了下代码
1. 查询时进行分页处理,处理时一页一页的处理.
2. 事务行为采用(PROPAGATION_REQUIRES_NEW,新建事务,如果当前存在事务,把当前事务挂起。)这样我处理一批(比如我设置粒度为10),就提交事务,这样,中间如果有异常,我最多损失10条数据,这10条数据再根据LOG进行处理. 当然这样频繁开启和提交事务,可能性能不太好.
还遇到过两个系统,但是数据源一样时,事务出现的问题
A系统保存了一个订单,订单号1001,然后把订单号1001传递给B系统,A系统等待B系统处理完返回结果,B系统会根据订单号1001去数据库查询,这个时候A系统是还没有提交事务的,那么B系统是查询不出来的,业务就走不下去了.
我之前的解决方法是 : A系统把保存了订单写一个单独的方法,事务行为是(PROPAGATION_REQUIRES_NEW),这样一旦保存后就立马提交到数据库了,B系统查询时就可以查询到记录了.(当然如果是分布式事务的话,就没有这个问题,只是当时什么构架,就这么处理了)
在实际项目中,可能还有很多关于事务传播行为不正确使用造成的问题,我们应该根据具体情况而使用不同的事务传播行为,而不是一概的使用PROPAGATION_REQUIRED.
遇到了几个事务坑后,让我更加重视在处理业务时事务行为的选择和搭配.
Spring 事务传播行为更详细的介绍
http://spring.cndocs.tk/transaction.html
http://blog.csdn.net/it_wangxiangpan/article/details/24180085
PROPAGATION_SUPPORTS : 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY : 支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW : 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED : 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER : 以非事务方式执行,如果当前存在事务,则抛出异常。
以上是Spring事务的传播行为,一般我们项目默认使用的是PROPAGATION_REQUIRED
如下图
1. 如果接口中方法需要语义化,那么可能会达不到基础项目默认配置的 声明式事务 申明的规则,从而没有被事务进行管理.
比如 : 购买XXX这个动作,buyXXX();如果声明式事务没有配置这项,那么需要自行加入配置
<tx:method name="buy*" propagation="REQUIRED"/>
否则事务没管理到,会出现一些数据不一致的问题.
如果觉得麻烦,那么可以声明式事务和注解式一起使用,在方法上加入
@Transactional @Override public void buyXXX(){ }
注解即可
2. 事务传播行为的选择,根据业务场景选择不同的传播行为
这是我在一个计划任务处理时踩的坑
业务场景 :
每个月给用户赠送一定量的话费.
我的处理方式是 :
查询出当月所有需要赠送的记录,然后for循环调外部API进行赠送处理.
问题 :
1. 查询出当月所有需要赠送的记录(如果数据量日渐增大,那么一次全部查询出来,会造成java.lang.OutOfMemoryError)
2. 事务使用的是(PROPAGATION_REQUIRED默认事务),并且如果中间出现像SQL连接中断,数据库锁获取失败(有遇到过锁获取了40分钟还没有获取到,导致异常)等等,那么数据全部回滚.如果数据有1w条,中间已经处理了9999条,到最后一条数据处理失败了,数据回滚不说,任务还需要重来.
3. 调外部API进行赠送处理,外部只给了你充值的功能,并不会给你扣款,或者冲正的接口,如果中间出异常数据回滚了,那么只会回滚当前系统数据库的数据.
我后面修改了下代码
1. 查询时进行分页处理,处理时一页一页的处理.
2. 事务行为采用(PROPAGATION_REQUIRES_NEW,新建事务,如果当前存在事务,把当前事务挂起。)这样我处理一批(比如我设置粒度为10),就提交事务,这样,中间如果有异常,我最多损失10条数据,这10条数据再根据LOG进行处理. 当然这样频繁开启和提交事务,可能性能不太好.
还遇到过两个系统,但是数据源一样时,事务出现的问题
A系统保存了一个订单,订单号1001,然后把订单号1001传递给B系统,A系统等待B系统处理完返回结果,B系统会根据订单号1001去数据库查询,这个时候A系统是还没有提交事务的,那么B系统是查询不出来的,业务就走不下去了.
我之前的解决方法是 : A系统把保存了订单写一个单独的方法,事务行为是(PROPAGATION_REQUIRES_NEW),这样一旦保存后就立马提交到数据库了,B系统查询时就可以查询到记录了.(当然如果是分布式事务的话,就没有这个问题,只是当时什么构架,就这么处理了)
在实际项目中,可能还有很多关于事务传播行为不正确使用造成的问题,我们应该根据具体情况而使用不同的事务传播行为,而不是一概的使用PROPAGATION_REQUIRED.
遇到了几个事务坑后,让我更加重视在处理业务时事务行为的选择和搭配.
Spring 事务传播行为更详细的介绍
http://spring.cndocs.tk/transaction.html
http://blog.csdn.net/it_wangxiangpan/article/details/24180085
相关文章推荐
- 项目实际开发中遇到的事务问题
- 实际项目开发中遇到的问题及解决办法
- spring管理的hibernate事务不会自动flush的问题-今天真遇到这问题了
- 在本地tomcat中调试Spring boot项目遇到的一些问题
- DWR在实际项目中的应用以及在调试过程中遇到的问题
- 新建一个maven spring boot项目中遇到的问题
- IDEA上面搭建一个SpringBoot的web-mvc项目遇到的问题
- spring boot 项目增加flyway的使用遇到问题解决
- Mybatis与spring项目中遇到的奇怪的问题:ClassNotFoundException: com.mysql.jdbc.Driver
- springboot项目打成war包部署到tomcat遇到的一些问题
- spring-boot创建项目遇到配置问题
- spring2.5整合ibatis2.3事务管理时遇到的问题以及需要的jar包
- spring 事务中遇到的----奇异问题
- Java GC机制及原理 项目实际遇到GC问题解决思路和经验总结
- 采用共享jar包部署struts2+spring集成项目会遇到的问题
- 项目增加spring-session模块所遇到的问题
- 遇到问题---maven---启动项目出现出现 java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoa
- springboot项目配置多环境打包部署遇到的问题总结
- 导入Mybatis_Spring项目遇到的问题
- BigDecimal在实际项目的应用及遇到的问题