spring 事务隔离级别、传播特性

隔离级别

 数据库中隔离级别四种

Isolation.DEFAULT  默认,使用数据库默认的隔离级别

隔离级别越往下,安全性越高,数据越安全。
Isolation.READ_UNCOMMITTED  读未提交,即使没有提交,但是做了更改也可以被读到。会产生脏读、幻读,不可重复读。
Isolation.READ_COMMITTED    读已提交,只读取已经提交的事务。会产生幻读,不可重复读。
Isolation.REPEATABLE_READ   可重复读,两个事务之间的读写不冲突。当一个事务进行数据读取,另一个事务进行了修改之后,第一个事务                                  再次读取,但是数据依旧和第一次读到的一样。可重复读
Isolation.SERIALIZABLE      序列化。效率低。不会脏读、幻读、重复读
System.out.println(" ------------ 事务类型 -----------");
//        test.transTestException(3,"zhang"); //执行过程中抛异常了,事务被回滚
//        test.transTestExceptionTry(3,"zhang"); //执行过程中异常被try了,事务不会回滚
//        test.transTestReadOnly(3,"zhang"); //只读事务,只读过程中不允许修改
//        test.transTestNoRoll(3,"zhang");//设置哪些异常不进行回滚,继续提交
//        test.transTestRollBack(3,"zhang");//遇到此类异常回滚,不进行提交

        System.out.println(" --------- 事务的 ACID 属性-----------");
        System.out.println(" A 原子性  要么完整执行,要么不执行");
        System.out.println(" B 一致性  一致性代表了底层数据存储的完整性");
        System.out.println(" I 隔离性  访问的数据不能受其它部分的影响");
        System.out.println(" D 持久性  对数据的修改都必须在事务结束前保存至物理存储中");


        System.out.println("------------ 事务隔离级别 从上往下隔离级别越来越高,数据也越安全-------------");

//      @Transactional(isolation = Isolation.DEFAULT)
//        Isolation.DEFAULT
        System.out.println(" 使用数据库默认的隔离级别");

//        Isolation.READ_UNCOMMITTED
        System.out.println("1. 读未提交 允许读取尚未提交的修改,可能导致脏读、幻读和不可重复");
        System.out.println(" 可以读取到已修改但是未提交事务的数据 (产生 : 脏读)");
//        Isolation.READ_COMMITTED
        System.out.println("2. 读已提交 允许从已经提交的事务读取,可防止脏读、但幻读,不可重复读仍然有可能发生");
        System.out.println(" 只能读取到已经提交事务的数据 产生不可重复读。 一个事务正在修改数据,另一个事务读取两次,在两次中间,另一个事务提交了,造成两次数据不一致(不可重复读)");
//        Isolation.REPEATABLE_READ
        System.out.println("3. 可重复读 对相同字段的多次读取的结果是一致的,除非数据被当前事务自身修改。可防止脏读和不可重复读,但幻读仍有可能发生");
        System.out.println(" 两个事务,独立执行。一个事务修改数据,另一个事务进行多次读取,即使第一个事务提交,第二次事务内(未提交前)读取的数据一致 。 会产生幻读");
//        Isolation.SERIALIZABLE
        System.out.println("4. 序列化   完全服从acid隔离原则,确保不发生脏读、不可重复读、和幻读,但执行效率最低");

        System.out.println(" ---数据不一致的问题 ---");
        System.out.println(" 脏读");
        System.out.println(" 不可重复读");
        System.out.println(" 幻读  由于可重复读,两个事务独立。当一个事务添加一条数据时,当前事务读取不到,插入一条相同数据时,但是该数据已经存在了。");

        System.out.println(" 锁机制 (粒度) 锁的粒度越小,效率越高。一般是行锁");
        System.out.println("1. 数据库级别");
        System.out.println("2. 表级别");
        System.out.println("3.  行");
        System.out.println(" --------- 事务的传播特性 7 ------------");

mysql默认的事务处理级别是'REPEATABLE-READ',也就是可重复读

oracle 默认系统事务隔离级别是READ COMMITTED,也就是读已提交

事务的隔离级别

如图,事务的传播特性有 7 个

 Propagation.REQUIRED  

如果有事务在运行,当前的这个方法就在事务内运行.否则就开启新的事务,在自己的事务内运行
@Transactional
    public void transPropagationTest(){
        transProReq(5,"zhangsan");
    }

    /* 如果有事务在运行,当前的这个方法就在事务内运行
     * 否则就开启新的事务,在自己的事务内运行
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void transProReq(Integer price,String name){
        transTestDao.updateBalance(name,price);
    }
Propagation.REQUIRES_NEW
当前的方法必须启动新事务,并在自己的事务内运行。如果有事务在运行,将它挂起
/* 当前的方法必须启动新事务,并在自己的事务内运行。如果有事务在运行,将它挂起
     */
@Transactional(propagation = Propagation.REQUIRES_NEW)
    public void transProReqNew(Integer price,String name){
        transTestDao.updateBalance(name,price);
    }
Propagation.MANDATORY
当前的方法必须运行在事务内部,如果没有正在运行的事务则抛出异常
/*
     *  当前的方法必须运行在事务内部,如果没有正在运行的事务则抛出异常
     */
    @Transactional(propagation = Propagation.MANDATORY)
    public void transProMan(Integer price,String name){
        transTestDao.updateBalance(name,price);
    }
Propagation.NEVER
当前的方法不应该运行在事务内,如果有运行的事务,就抛出异常
/*
     *  当前的方法不应该运行在事务内,如果有运行的事务,就抛出异常
     */
    @Transactional(propagation = Propagation.NEVER)
    public void transProNever(Integer price,String name){
        transTestDao.updateBalance(name,price);
    }
Propagation.NESTED
如果有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行。否则就启动一个新的事务,在自己的事务内运行。

如果里面的事务没有异常则不回滚,如果外面的事务有异常没被捕获,里面的事务才会被回滚。

/*
     *  如果有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行。
     *  否则就启动一个新的事务,在自己的事务内运行。
     */
    @Transactional(propagation = Propagation.NESTED)
    public void transProNested(Integer price,String name){
        transTestDao.updateBalance(name,price);
    }
Propagation.SUPPORTS
如果有事务在运行,当前的方法就在这个事务内运行.否则它可以不运行在事务中
/*
     *  如果有事务在运行,当前的方法就在这个事务内运行
     *  否则它可以不运行在事务中
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    public void transProSupports(Integer price,String name){
        transTestDao.updateBalance(name,price);
    }

Propagation.NOT_SUPPORTED
当前的事务不应该运行在事务中,如果有运行的事务,就将它挂起 

/*
     *  当前的事务不应该运行在事务中,如果有运行的事务,就将它挂起
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void transProNotSupports(Integer price,String name){
        transTestDao.updateBalance(name,price);
    }

猜你喜欢

转载自blog.csdn.net/dandanforgetlove/article/details/106750107