本文是<实现 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 行为需要做的只有草率的处理掉当前连接。然后恢复上一个事务就可以了。
来源:oschina
链接:https://my.oschina.net/u/1166271/blog/200416