使用spring事务操作事务不能保证绝对的安全

背景

经常听同事信誓旦旦的说使用通过sping事务操作数据库可以保证绝对的安全,但是本文想抬杠一下,使用spring事务虽然可以保证对于数据库来说事务要么执行要么回滚,但是对于应用程序,也就是spring所在应用进程来说,极端情况下它并不知道事务的执行结果,也就是它没法确认事务到底是成功了还是失败了。这么说是不是听上去很奇怪?为什么sping所在的应用程序没法确认事务是否成功执行还是失败回滚的呢?

真相追踪

我们假设我们的应用程序代码如下:

private boolean doTrasaction(){
	try{
		   begin trasaction;
		   ....
		   commit;	// 提交事务
	}catch(Exception e){
		rollback(); // 回滚事务
		throw e;
	}
}

我们假设使用spring事务执行如上所示的代码,正好在commit提交事务的时候网络中断,如下图所示
模拟数据库返回的相应丢失
我们可以确认数据库确实完整执行了所提交的事务,但是假设数据返回的commit响应丢失,那么我们应用程序此时是什么状态呢?
可以确认的是我们应用程序肯定会收到一个网络中断的异常,那么问题就来了,网络中断异常的背后到底是对应事务已经回滚还是事务已经成功执行?事实上,此时对于应用程序来说它并不知道数据库事务的执行情况,因为不论此时我们是假设事务成功执行还是回滚都不正确,单纯通过应用程序本身已经没法判断事务的执行状态。

小结

那这种情况下应用程序应该怎么处理呢?正确的处理要分几种情况:
1.首先简单的重试事务肯定不是安全的,因为对于数据库来说重试意味着一个新的事务重新执行,比如扣款的话已经扣了两次
2.保险的做法是重新判断此时数据库记录的状态来决定是重试还是做其他的操作
其实这种情况下就又涉及到端到端的一致性保证以及幂等性等话题了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值