事务的传播,隔离级别,编程式事务,声明式事务

事务的传播机制

在一个事务调用另一个事务方法时,就会存在事务的传播。

@service

public class AService {

        @Autowried

        private BService bservice;

        

        public viod order() {

                yyyyy();

                bserivce.xxx();

                zzzz();

        }
}

        其中理想的执行方式是,A事务开启,执行yyyyy() 方法后,开启B事务,执行调用的方法,结束B事务,最后执行A事务未执行完的方法。两个事务是以嵌套的形式执行,两者互不影响,即事务B出现问题需要回滚时,不会回滚到A的事务里面去。

        然而在mysql不支持这种嵌套事务的方式。当两个都有事务时,它的执行方式是:开启事务执行yy()----》在遇到第二个事务时就会进行把第一个事务提交----》开启第二个事务----》执行XXX()----》结束事务-----》无事务的处理方式执行zzzz();

        对于这种情况的解决方案有如下几种。

  • 让传递过来的事务进行融入到外层事务中,只开启一个事务,执行全部操作
    • 该方法的弊端是,两个事务合在一起,只要那一步出现问题,导致全部一起回滚。
  • 用不同的连接进行分隔两个事务,外层事务用一个连接执行,执行一部分,挂起;启用另外一个连接执行内层事务,执行完成触发之前的连接继续执行外层的事务.
    • 两者存在同步的机制,即内层事务执行完需要把外层的事务给唤醒。
  • 嵌套事务,mybatis模拟嵌套事务。通过设置保存点,将内部事务转化为通过保存点和回滚保存点,实现类似两个事务的操作。
    • 当内部事务出现问题,只会回滚到保存点。

begin;

        update xxx;

        SAVEPOINT a;

                update xxx;

                update  xxx;

        ROLLBACK to a;

        update xxx;

commit;

传播行为

  • propagation_required:表示外层有事务就融入进去,外层没有事务就开启一个事务。
  • propagation_supports:B支持A,如果外界有事务,就融入,没有事务就以无事务方式执行。(只读事务,查询事务)
  • propagation_mandatory:(强制性的)外界必须有事务,无事务则会抛出异常。
  • propagation_requires_new:如果外界有则把外界的挂起,自己新开启一个事务,如果外界没有,也开启一个事务。(不管有无都自己开启新的事务)
  • propagation_not_supported:(不支持事务)表示该方法不应该运行在事务中,外界有事务,则挂起,自己以非事务的方式运行。外界无事务,自己也是无事务的运行方式。
  • propagation_never:(不会运行在有事务的环境),有事务运行则抛出异常。
  • propagation_nested:(嵌套的)类似嵌套的方式。

事务的隔离级别

        数据库事务的隔离级别有4种,

  •  Read Uncommited,读未提交,即一个事务可以读取另一个未提交事务的数据;并发操作会导致脏读
  • Read Commited,读已提交,即一个事务要等到另一个事务提交后才能读取数据;解决脏读问题;并发操作会导致不可重复读
  • Repeatable Read,重复读,即开始读取数据(事务开启)时,不再允许修改操作;解决不可重复读问题;并发操作会导致幻读(对应insert操作)
  • Serializable,序列化,最高的事务隔离级别,该级别下,事务串行化顺序执行;避免脏读、不可重复读与幻读;但是该级别效率低下,比较消耗数据库性能,一般不用。

    脏读 不可重复读 幻读
    读未提交
    读已提交
    重复读
    序列化

    编程式事务和声明式事务

  • 编程式事务:通过编码的形式,实现事务,其全部代码逻辑都是在同一个方法中实现的。
  • 声明式事务:在AOP基础上,受aop的管理,其本质是对方法前后进行拦截,使用注解的方式,对事务进行管理。

你可能感兴趣的:(java,mysql,开发语言)