spring学习---事务传播属性和隔离级别

目录

  • spring事务传播属性
  • 数据库定义隔离级别
  • spring定义隔离级别

1. spring事务传播属性

Spring 事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring 是无法提供事务功能的
spring保护的事务传播属性有以下这些(枚举类Propagation定义,引用TransactionDefinition类的常量)

常量名称常量解释
PROPAGATION_REQUIRED支持当前事务,如果当前没有事务,就新建一个事务,spring默认属性
PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行
PROPAGATION_MANDATORY支持当前事务,如果当前没有事务,就抛出异常
PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。新建的事务将和被挂起的事务没有任何关系,是两个独立的事务,外层事务失败回滚之后,不能回滚内层事务执行的结果,内层事务失败抛出异常,外层事务捕获,也可以不处理回滚操作
PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常
PROPAGATION_NESTED如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED 属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影

1.1 PROPAGATION_REQUIRED

**作用:**支持当前事务,如果当前没有事务,就新建一个事务
举例:

//事务属性 PROPAGATION_REQUIRED
methodA{
    ……
    methodB();
    ……
}
//事务属性 PROPAGATION_REQUIRED
methodB{
   ……
}

说明: 当方法B执行时,会启动事务,方法A使用与B同一个事务

1.2 PROPAGATION_SUPPORTS

**作用:**支持当前事务,如果当前没有事务,就以非事务方式执行
举例:

//事务属性 PROPAGATION_REQUIRED
methodA(){
  methodB();
}

//事务属性 PROPAGATION_SUPPORTS
methodB(){
  ……
}

说明: 单纯使用B方法时,以非事务的方式执行,执行A方法时,方法B加入A的事务进行执行。

1.3 PROPAGATION_MANDATORY

**作用:**支持当前事务,如果当前没有事务,就抛出异常
举例:

//事务属性 PROPAGATION_REQUIRED
methodA(){
  methodB();
}

//事务属性 PROPAGATION_MANDATORY
methodB(){
  ……
}

说明: 单纯使用B方法时,因为当前方法没有一个活动的事务,会报IllegalTransactionStateException异常,执行A方法时,方法B加入A方法事务正常执行

1.4 PROPAGATION_REQUIRES_NEW

**作用:**总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起,需要使用JtaTransactionManager作为事务管理器
举例:

//事务属性 PROPAGATION_REQUIRED
methodA(){
    doSomeThingA();
    methodB();
    doSomeThingB();
}

//事务属性 PROPAGATION_REQUIRES_NEW
methodB(){
    ……
}

说明: 单纯使用B方法时,正常启用一个事务进行执行。
使用方法A时运行流程

main(){
    TransactionManager tm = null;
    try{
        //获得一个JTA事务管理器
        tm = getTransactionManager();
        tm.begin();//开启一个新的事务
        Transaction ts1 = tm.getTransaction();
        doSomeThing();
        tm.suspend();//挂起当前事务
        try{
            tm.begin();//重新开启第二个事务
            Transaction ts2 = tm.getTransaction();
            methodB();
            ts2.commit();//提交第二个事务
        } Catch(RunTimeException ex) {
            ts2.rollback();//回滚第二个事务
        } finally {
            //释放资源
        }
        //methodB执行完后,恢复第一个事务
        tm.resume(ts1);
        doSomeThingB();
        ts1.commit();//提交第一个事务
    } catch(RunTimeException ex) {
        ts1.rollback();//回滚第一个事务
    } finally {
        //释放资源
    }
}

1.5 PROPAGATION_NOT_SUPPORTED

**作用:**以非事务方式执行操作,如果当前存在事务,就把当前事务挂起,需要使用JtaTransactionManager作为事务管理器,可以参考上面一个属性,只是不重启新的第二个事务

PROPAGATION_NEVER

**作用:**总是非事务地执行,如果存在一个活动事务,则抛出异常

1.6 PROPAGATION_NESTED

**作用:**如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行。这是一个嵌套事务,使用JDBC 3.0驱动时,仅仅支持DataSourceTransactionManager作为事务管理器。需要JDBC 驱动的java.sql.Savepoint类。有一些JTA的事务管理器实现可能也提供了同样的功能。使用PROPAGATION_NESTED,还需要把PlatformTransactionManager的nestedTransactionAllowed属性设为true;而 nestedTransactionAllowed属性值默认为false。
举例:

//事务属性 PROPAGATION_REQUIRED
methodA(){
    doSomeThingA();
    methodB();
    doSomeThingB();
}

//事务属性 PROPAGATION_NESTED
methodB(){
    ……
}

说明: 当方法B执行时,按照REQUIRED属性方式执行
执行方法A时

main(){
    Connection con = null;
    Savepoint savepoint = null;
    try{
        con = getConnection();
        con.setAutoCommit(false);
        doSomeThingA();
        savepoint = con2.setSavepoint();
        try{
            methodB();
        } catch(RuntimeException ex) {
            con.rollback(savepoint);
        } finally {
            //释放资源
        }
        doSomeThingB();
        con.commit();
    } catch(RuntimeException ex) {
        con.rollback();
    } finally {
        //释放资源
    }
}

当methodB方法调用之前,调用setSavepoint方法,保存当前的状态到savepoint。如果methodB方法调用失败,则恢复到之前保存的状态。但是需要注意的是,这时的事务并没有进行提交,如果后续的代码(doSomeThingB()方法)调用失败,则回滚包括methodB方法的所有操作。
嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚

2. 数据库定义隔离级别

隔离级别导致的问题
Read-Uncommitted0导致脏读
Read-Committed1避免脏读,允许不可重复读和幻读(默认的)
Repeatable-Read2避免脏读,不可重复读,允许幻读
Serializable3串行化读,事务只能一个一个执行,避免了脏读、不可重复读、幻读。执行效率慢,使用时慎重

2.1 脏读:

一事务对数据进行了增删改,但未提交,另一事务可以读取到未提交的数据。如果第一个事务这时候回滚了,那么第二个事务就读到了脏数据。

2.2 不可重复读:

一个事务中发生了两次读操作,第一次读操作和第二次操作之间,另外一个事务对数据进行了修改,这时候两次读取的数据是不一致的。
###2.3 幻读:
第一个事务对一定范围的数据进行批量修改,第二个事务在这个范围增加一条数据,这时候第一个事务就会丢失对新增数据的修改。

2.4 总结:

隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。
大多数的数据库默认隔离级别为Read Commited,比如SqlServer、Oracle
少数数据库默认隔离级别为:Repeatable Read 比如: MySQL InnoDB

3. spring定义隔离级别

Isolation枚举类中定义了值

隔离级别含义
ISOLATION_DEFAULT使用数据库默认的事务隔离级别,默认的隔离级别
ISOLATION_READ_UNCOMMITTED对应数据库级别的Read-Uncommitted
ISOLATION_READ_COMMITTED对应数据库级别的Read-Committed,它充许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读
ISOLATION_REPEATABLE_READ对应数据库级别的Repeatable-Read,可以防止脏读,不可重复读。但是可能出现幻像读
ISOLATION_SERIALIZABLE对应数据库级别的Serializable,串行化读,事务只能一个一个执行

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值