事务的传播行为(propagation)

事务的7中传播行为

  1. PROPAGATION_REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
  2. PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
  3. PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
  4. PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。也比较常见。
  5. PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  6. PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

比较容易混淆的是这三个传播行为:PROPAGATION_REQUIRED、PROPAGATN_REQUIRES_NEW、PROPAGATION_NESTED

  • PROPAGATION_REQUIRED嵌套时,不管是否用try catch,只要里外二个事务有一个出错,都会因rollback。因为是同一个事务范围。
  • PROPAGATN_REQUIRES_NEW被嵌套时,外面的事务不会影响里面的事务。如果里面的事务用了try catch,那么出错外面不会rollback,里面rollback。如果没用,里面的抛出错,会导致里外的事务都rollback。
  • PROPAGATION_NESTED最有意思。它被嵌套时,实际上是起的一个子事务。外面的事务rollback了,里面的也rollback。如果里面的事务用了try catch,那么出错外面不会rollback,里面rollback。如果没用,里面的抛出错,会导致里外的事务都rollback。

代码示例

spring配置

java代码

业务案例

一般情况我们使用默认的传播行为就行了,但是有些相对特殊的情况,需要使用其他的用法,举个例子:

某个也事务中执行一个业务逻辑,该业务逻辑中写数据一条数据A,并在事务结束前发出去一条消息给其他的应用,其他的应用受到消息会先来查询数据A,然后你很可能会发现其他应用来查询A时发现A并不存在。原因就是整个事务相关的还未commit,其他不在事务中的查询DB请求都读取不到未commit的数据(一般都是读已提交的事务隔离级别ISOLATION_READ_COMMITTED)

参考资料