zhaoyu@home:~$

spring事务

spring事务NESTED和REQUIRE_NEW的区别

NESTED 不会开启新的事务,相当与保存点。
REQUIRE_NEW开启一个新的事务,只要事务关联的方法没有异常,就会提交,和外部的事务没有关系。

我们先定义3个事务,如下:

  1. 父事务P,向数据库表中插入id为0的行。
  2. 子事务S1,向数据库表中插入id为1的行。
  3. 子事务S2,向数据库表中插入id为2的行。

父事务的方法m调用了子事务的方法m1和m2。如下

m(){
    m1();
    m2();
}

如有父事务P是默认的REQUIRE,子事务是REQUIRE_NEW:

  1. 如果父事务发生了异常,那么父事务回滚,子事务提交。数据库中记录为1,2
    调用逻辑如下:
    m(){
         m1();
         m2();
         throw e; //父事务发生了异常,子事务正常
    }
    
  2. 如果子事务发生了异常,那么子事务回滚,父事务也回滚,父方法相当于也发生了异常。 数据库中结果为1,因为m1没发生异常且独立提交。
    m(){
         m1();
         m2(); //throw e; 子事务S2方式了异常
    }
    
  3. 如果子事务发生了异常,那么子事务回滚,父事务捕获并未重新抛出异常,父方法相当于没发生异常,则父事务不回滚。 数据库中结果为0,1
    m(){
        try{
            m1();
            m2(); //throw e; 子事务S2方式了异常
        }catch(e){}
    }
    

如有父事务是默认的REQUIRE,子事务是NESTED:

  1. 如果父事务发生了异常,那么父事务回滚,子事务也回滚。数据库中没有记录。
    调用逻辑如下:
    m(){
         m1();
         m2();
         throw e; //父事务发生了异常,子事务正常
    }
    
  2. 如果子事务发生了异常,那么子事务回滚,父事务也回滚,父方法相当于也发生了异常。 数据库中没有记录。
    m(){
         m1();
         m2(); //throw e; 子事务S2方式了异常
    }
    
  3. 如果子事务发生了异常,那么子事务回滚,父事务捕获并未重新抛出异常,父方法相当于没发生异常,则父事务不回滚。 数据库中结果为0,1
    m(){
        try{
            m1();
            m2(); //throw e; 子事务S2方式了异常
        }catch(e){}
    }
    

如有父事务是默认的REQUIRE,子事务是REQUIRE:在上述第三种情况下,整个事务都会回滚,这就是REQUIRE和NESTED的区别。