脱离 Spring 实现复杂嵌套事务,之六(NOT_SUPPORTED - 非事务方式)

原创
2014/02/17 12:15
阅读数 1.1W

    本文是<实现 Spring 的事务控制>系列文章中一篇。本文假设读者已经阅读并理解《实现 Spring 的事务控制,之一(必要的概念)》文中所涉及的概念(当前连接引用计数),以及数据库连接的(new状态

PROPAGATION_NOT_SUPPORTED (非事务方式)

定义:

    是指如果存在事务则将这个事务挂起,并使用新的数据库连接。新的数据库连接不使用事务。

解释:

    NOT_SUPPORTED 行为是 Spring 为我们带来的一种特殊的事务控制行为。在这种行为下它保证了当前对数据库的操作是相当于 autoCommit 值为 true 。

    我们回顾第一篇文章中提到的银行转账业务:“A账户可以转账给B账户,银行要求能看到当前实时的正在交易的笔数”。我们曾在《REQUIRES_NEW - 独立事务》一文中见到过如何实现这个需求。现在我在像大家介绍如何通过使用 NOT_SUPPORTED 行为实现同样的业务。

时间 事务1(开启事务) 事务2(非事务)
T1 开始事务
T2
挂起事务
T3
记录日志...
T4
恢复事务
T5 转账500元
T6
挂起事
T7
记录日志
T8
恢复事务
T9 递交事务

    我们先看事务1,在事务1中展示的是一个完整的转账业务功能。它被一个事务所环抱,这个事务保证了转账业务的正确执行。

    下面我们看一看事务2中是如何处理日志记录的。

     首先事务2在记录日志之前挂起了当前事务,还记得前面在REQUIRES_NEW - 独立事务》一文中提到的“挂起”操作和“Suspent特征”么?

     事务2在 NOT_SUPPORTED 行为下,会挂起当前事务。与 REQUIRES_NEW 行为不同的是,它在挂起之后不会在尝试开启新的事务。也就是这一点的区别决定了 NOT_SUPPORTED 行为与 REQUIRES_NEW 行为。

工作原理


开启事务

    事务管理器在创建 NOT_SUPPORTED 行为事务时,会取得当前连接这一过程会持有当前连接(引用计数+1)。注意:此时持有的数据库连接并不一定是最终在操作阶段使用的数据库连接

    然后通过判断当前连接是否存在事务状态,来决定是否通过 执行挂起事务操作。一旦执行了挂起事务的操作就相当于清空了当前的数据库连接。所以接下来需要重新申请一个数据库连接,新申请的数据库连接事务管理器也会持有它(引用计数+1)。

    不同于 REQUIRES_NEW 行为的是,在 NOT_SUPPORTED 行为下事务管理器是不会开启新连接的事务的。也就是说当前连接是不会被标记“new”状态。它一直工作在非事务模式下。

事务中的数据库操作

    无论在开启事务的时候Connection 此时此刻,可以直接使用 Connection 接口畅快的使用数据库操作。由于每次进行数据库操作都要反复的申请和释放数据库连接。这会反复的使引用计数 +1,-1。

递交/回滚事务

   最后由于不需要管理当前连接的事务,NOT_SUPPORTED 行为需要做的只有草率的处理掉当前连接。然后恢复上一个事务就可以了。


展开阅读全文
打赏
3
14 收藏
分享
加载中
大佬,请教一个问题。
aService里的方法调用了bService的一个方法,bService方法报错,aService事务继续提交。用事务传播能解决问题吗?
例如我一个业务方法,方法最后调用记录日志的其他方法,记录日志保错,但是不要影响业务方法提交,用事务传播来解决
2019/07/10 17:08
回复
举报
哈库纳博主
用 独立事务 模式
2019/07/23 19:27
回复
举报
哈库纳博主

引用来自“骑马的奥巴”的评论

A方法包含B方法,B方法的事物是NOT_SUPPORTED,A方法的事物是PROPAGATION_REQUIRED,那B如果里面报错了,A方法会不会回滚
B 不回滚,A回滚。 因为用了两个数据库连接来实现这样的隔离。
2017/07/01 23:14
回复
举报
那博主这个转账的例子是:事务2包含事务1吗?
2019/07/10 19:09
回复
举报
哈库纳博主
这个 Case 我当时的回答应该是有问题的, A 方法中包含了 B 方法,B 方法 标记了 NOT_SUPPORTED
如果 A 方法中启动了事务,那么根据 NOT_SUPPORTED 应该是会引发异常的。
2019/07/23 19:29
回复
举报
A方法包含B方法,B方法的事物是NOT_SUPPORTED,A方法的事物是PROPAGATION_REQUIRED,那B如果里面报错了,A方法会不会回滚
2017/07/01 21:33
回复
举报
哈库纳博主

引用来自“拖布普斯”的评论

我这个有点问题,aService里面有个bBo方法,首先aService存在事物,但是bBo不支持事物,按照你的说法,不支持事物是自动提交的,我在bBo处理完数据后,aService出现异常,为什么bBo的数据也会回滚?他不是已经提交了吗?
这个要看你用的框架具体实现细节,最好的方式是直接分析它的源码。
2017/06/26 16:56
回复
举报
我这个有点问题,aService里面有个bBo方法,首先aService存在事物,但是bBo不支持事物,按照你的说法,不支持事物是自动提交的,我在bBo处理完数据后,aService出现异常,为什么bBo的数据也会回滚?他不是已经提交了吗?
2017/06/26 16:52
回复
举报
哈库纳博主

引用来自“huangshiming”的评论

哥们,分析得不错,但你这文章是看源码分析的吗??如果是经过严谨的分析,你这系列的文章应该推广出去,因为很多人对事务的传播性还是似懂非懂的。
对着Spring源码的分析,同时根据SpringJDBC的原理我也给出了一套简化版的实现。 如果有兴趣可以参考框架DB部分的实现:http://git.oschina.net/zycgit/hasor
2016/02/29 13:45
回复
举报
哥们,分析得不错,但你这文章是看源码分析的吗??如果是经过严谨的分析,你这系列的文章应该推广出去,因为很多人对事务的传播性还是似懂非懂的。
2016/02/27 11:02
回复
举报
哈库纳博主

引用来自“一辈子的码农”的评论

看不懂
从第一篇开始看。
2015/10/20 19:07
回复
举报
看不懂
2015/09/22 21:29
回复
举报
更多评论
打赏
12 评论
14 收藏
3
分享
返回顶部
顶部