跳到主要内容

事务传播行为

提示

事务传播行为率先出现在 Spring 框架中,dbVisitor 对其思想并未有什么改进而是在 dbVisitor 中提供了一套完整的实现。

简单的理解就是多个事务方法相互调用时,事务如何在这些方法间传播。举个例子:

方法A 是一个事务的方法,在执行过程中调用了 方法B。 接下来 方法B 有无事务以及 方法B 对事务的要求不同都会对 方法A 的事务具体执行造成影响。 同时 方法A 的事务对 方法B 的事务执行也有影响,这种影响具体是什么就由两个方法所定义的事务传播行为所决定。

加入已有事务 (REQUIRED)

  • dbVisitor 常量 Propagation.REQUIRED

尝试加入已经存在的事务中,如果没有则开启一个新的事务。

时间事务1事务2(REQUIRED)效果
T1begin
T2insert data1
T3begin什么都不做
T4insert data2
T5commit/rollback什么都不做
T5insert data3
T5commit/rollback

独立事务 (REQUIRES_NEW)

  • dbVisitor 常量 Propagation.REQUIRES_NEW

将挂起当前存在的事务挂起(如果存在的话)并且开启一个全新的事务,新事务与已存在的事务之间彼此没有关系。

  • 挂起会导致 DataSourceManager 中正在使用的同步资源被临时保存
  • 在挂起之后访问 DataSourceManager 会得到一个全新的数据库连接。
时间事务1事务2(REQUIRES_NEW)效果
T1begin
T2insert data1
T3begin产生新的连接并且和当前线程绑定,以满足 本地同步
T4insert data2在新连接上写入
T5commit/rollback操作新的 Connection
T5insert data3
T5commit/rollback

嵌套事务 (NESTED)

  • dbVisitor 常量 Propagation.NESTED

在当前事务中通过 Savepoint 方式开启一个子事务。

时间事务1事务2(NESTED)效果
T1begin
T2insert data1
T3begin创建事务保存点
T4insert data2
T5commit/rollbackcommit 会释放保存点、rollback 会回退到 T3
T5insert data3
T5commit/rollback

跟随环境 (SUPPORTS)

  • dbVisitor 常量 Propagation.SUPPORTS

如果当前没有事务存在,就以非事务方式执行;如果有,就使用当前事务。以下面的执行为例:

  • SUPPORTS 行为是事务传播属性中最简单的一种行为,其行为本质上强调了 不作为
时间事务1事务2(SUPPORTS)效果
T1begin
T2insert data1
T3begin
T4insert data2注1 若 T1 开启了事务,那么效果等同于 REQUIRED
T5commit/rollback什么都不做
T5insert data3
T5commit/rollback
  • 注1 开启了事务指的是 Connection 对象的 autoCommit 属性为 false。 能够导致启动事务的传播行为有 REQUIREDREQUIRES_NEWNESTED,如果使用 低级别 API 手动改变 autoCommit 状态也会导致进入事务状态。

非事务方式 (NOT_SUPPORTED)

  • dbVisitor 常量 Propagation.NOT_SUPPORTED

如果当前没有事务存在,就以非事务方式执行;如果有,就将当前事务挂起。以下面的执行为例:

信息

将挂起当前存在的事务挂起(如果存在的话)并且开启一个全新的事务,新事务与已存在的事务之间彼此没有关系。

  • 挂起会导致 DataSourceManager 中正在使用的同步资源被临时保存。
  • 在挂起之后访问 DataSourceManager 会得到一个全新的数据库连接。
时间事务1事务2(NOT_SUPPORTED)效果
T1begin
T2insert data1
T3begin注1 若 T1 开启了事务,那么会挂起当前事务。但不开启新的事务
T4insert data2
T5commit/rollback注2 若 T3 挂起了事务,那么会恢复它。
T5insert data3
T5commit/rollback
  • 注1 开启了事务指的是 Connection 对象的 autoCommit 属性为 false。 能够导致启动事务的传播行为有 REQUIREDREQUIRES_NEWNESTED,如果使用 低级别 API 手动改变 autoCommit 状态也会导致进入事务状态。
  • 注2 恢复挂起的事务会更新 DataSourceManager 的当前绑定连接为之前的那一个。

排除事务 (NEVER)

  • dbVisitor 常量 Propagation.NEVER

如果当前没有事务存在,就以非事务方式执行;如果有就抛出异常。

时间事务1事务2(NEVER)效果
T1begin
T2insert data1
T3begin注1 若 T1 开启了事务,那么会抛出异常
T4insert data2
T5commit/rollback什么都不做
T5insert data3
T5commit/rollback
  • 注1 若 T1 这个动作为 NOT_SUPPORTED 那么 T3 环节上 NEVER 行为就不会报错。它的行为会和 SUPPORTS 等价。 若 T1 这个动作导致了 Connection 对象的 autoCommit 属性为 false 那么 T3 环节就会报错。
  • 能够导致 autoCommitfalse 传播行为有 REQUIREDREQUIRES_NEWNESTED,也可以通过使用 低级别 API 改变。

要求事务 (MANDATORY)

  • dbVisitor 常量 Propagation.MANDATORY

如果当前没有事务存在,就抛出异常;如果有,就使用当前事务。

时间事务1事务2(NEVER)效果
T1begin
T2insert data1
T3begin注1 若 T1 不存在事务,那么会抛出异常
T4insert data2
T5commit/rollback什么都不做
T5insert data3
T5commit/rollback
  • 注1 与上面刚刚好相反 MANDATORY 是要求必须 T1 环节产生了一个事务,否则会报错。 因此若 T1 环节使用的是 NOT_SUPPORTED 行为,那么 T3 环节就会报错。