spring 事务的七种传播机制与四种隔离级别

一. spring 事务的七种传播机制

事务传播行为是为了解决业务层方法之间互相调用的事务问题.

1. PROPAGATION_REQUIRED (注解 @Transactional 默认使用的传播机制)

若当前存在事务, 则加入该事务. 若不存在事务, 则新建一个事务.

class C1 {
    @Transactional(propagation = PROPAGATION.REQUIRED)
    function A() {
        C2.B();            
    }    
}

class C2 {
    @Transactional(propagation = PROPAGATION.REQUIRED)
    function B() {
        do something;           
    }    
}
  • spring在调用methodA的时候没有事务,因此创建一个新的事务,而methodA中又调用了methodB,而此时已经存在一个事务了,所以methodB会加入到这个事务中
    对于第二个方法,由于methodB此时没有事务,因此spring会开启一个新的事务。spring会确保方法中的所有调用都得到一个相同的连接。
  • A, B 可以操作同一条纪录, 因为处于同一个事务中.

2. PROPAGATION_REQUIRED_NEW

若当前不存在事务, 则新建一个事务. 若当前存在事务, 则将当前事务挂起, 新建一个事务. 即不管外部方法有无事务, PROPAGETION_REQUIRED_NEW 修饰的内部方法都会开启一个新事务, 且开启的事务相互独立, 互不干扰. 外部事务抛出异常回滚不会影响内部事务正常提交.

class C1 {
    @Transactional(propagation = PROPAGATION.REQUIRED)
    function A() {
        do somethingA();
       C2.B();   
       do somethingB();                
    }    
}

class C2 {
    @Transactional(propagation = PROPAGATION.REQUIRED_NEW)
    function B() {
        do something;           
    }    
}
  • 这两段代码在一起。此时methodA会创建一个新的事务tr1,而methodA在执行到methodB()方法时,调用methodB方法,此时methodB方法又会创建一个新的事务tr2,这两个事务是没有关联相互独立的,如果methodA中在执行完methodB方法之后的doSomeThingB()方法执行失败了,那么methodA方法的数据会执行回滚不会提交,但是其中的methodB的数据仍然会提交到数据库中,这表明tr1和tr2之间是独立的。也就是说,只要methodB成功执行了,那么methodB的数据就会被加入到数据库,不管其后面的代码是否发生异常。如果使PROPAGATION_REQUIRES_NEW,需要使用JtaTransactionManager作为事务管理器。
  • A,B 不可操作同一条纪录, 因为处于不同事务, 会产生死锁.

3. PROPAGATION_NESTED (嵌套事务)

如果当前存在事务, 则创建一个事务作为当前事务的嵌套事务来运行; 如果当前没有事务, 则该取值等价于 propagation_required

class C1 {
    @Transactional(propagation = PROPAGATION.REQUIRED)
    function A() {
        do somethingA();
        C2.B();   
        do somethingB();         
    }    
}

class C2 {
    @Transactional(propagation = PROPAGATION.NESTED)
    function B() {
        do something;           
    }    
}
  • 这里如果单独调用methodB方法,则按照PROPAGATION_REQUIRED属性执行。
  • 如果调用methodA方法,那么在执行methodA方法内调用methodB方法的时候,会先调用setSavePoint方法,保存当前的状态到savepoint中,如果methodB方法调用失败,则恢复到之前记录的那个状态,然后继续执行后续代码,此时事务都还没有提交,如果其后面的doSomeThingB()方法调用失败,则回滚包括methodB在内的所有操作。也就是所:这是一个嵌套事务,嵌套事务的内层事务依赖于外层事务,如果外层事务失败时,会回滚内层事务,而内层事务操作失败的时候,并不会引起外层事务的回滚,外层事务会回复到内层事务执行之前的状态,然后继续执行后面的方法。

4. PROPAGATION_SUPPORTS

如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

5. PROPAGATION_NOT_SUPPORTS

以非事务方式运行,如果当前存在事务,则把当前事务挂起。

6. PROPAGATION_MANDATORY (很少使用)

如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)

7. PROPAGATION_NEVER

以非事务方式运行,如果当前存在事务,则抛出异常。

注:
PROPAGATION_NESTED 与 PROPAGATION_REQUIRES_NEW 的区别:这两个事物的最大区别是 PROPAGATION_NESTED 是一个嵌套事务,内层事务依赖于外层事务,内层事务成功执行完成之后,数据其实并没有提交到数据库,而需要外层事务全部成功完成之后,内外层数据才会提交到数据库,若内层事务虽然成功执行,但是外层事务在其之后发生异常,则内层事务和外层事务全部回滚;
而 PROPAGATION_REQUIRES_NEW 是完全两个不同的事务,相互之间是独立的,一旦内层事务提交了,外层事务发生异常也并不能让内层事务回滚。

二. spring 事务的四种隔离级别

1. 事务四大特性 (ACID)

原子性 --> 操作要么全部成功, 要么全部回滚.
一致性 --> 事务执行前后处于一致性状态.
隔离性 --> 事务直接互不干扰.
持久性 --> 事务一旦提交, 数据的改变是永久性的. 即使数据库发生故障, 数据也不会丢失.

2. 事务隔离级别相关问题

脏读
脏读指事务A读到了事务B还没有提交的数据。 A事务对一条记录进行修改,尚未提交,B事务已经看到了A的修改结果。若A发生回滚,B读到的数据就是错误的,这就是脏读。

不可重复读
在一个事务里面读取了两次某个数据,读出来的数据不一致。A事务对一条记录进行修改,尚未提交,B事务第一次查询该记录,看到的是修改之后的结果,此时A发生回滚,B事务又一次查询该记录,看到的是回滚后的结果。同一个事务内,B两次查询结果不一致,这就是不可重复读。

幻读
所谓幻读,就是指在一个事务里面的操作中发现了未被操作的数据。比如学生信息,事务A开启事务-->修改所有学生当天签到状况为false,此时切换到事务B,事务B开启事务-->事务B插入了一条学生数据,此时切换回事务A,事务A提交的时候发现了一条自己没有修改过的数据,这就是幻读,就好像发生了幻觉一样。幻读出现的前提是并发的事务中有事务发生了插入、删除操作。

3. 事务的隔离级别

和事务传播行为这块一样,为了方便使用,Spring 也相应地定义了一个枚举类:Isolation

public enum Isolation {
    
    // 使用后端数据库默认的隔离级别 (MySQL --> REPEATABLE_READ, Oracle --> READ_COMMITTED)
    DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),
    
    // 读未提交
    READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),
    
    // 读提交
    READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),
    
    // 可重复读 ---> innodb默认隔离级别
    REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),
 
    // 序列化
    SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);

    private final int value;

    Isolation(int value) {
        this.value = value;
    }

    public int value() {
        return this.value;
    }

}

ISOLATION_DEFAULT
使用后端数据库默认的隔离级别,MySQL 默认采用的 REPEATABLE_READ 隔离级别, Oracle 默认采用的 READ_COMMITTED 隔离级别

ISOLATION_READ_UNCOMMITTED --> 读未提交
最低的隔离级别,使用这个隔离级别很少,因为它允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读

ISOLATION_READ_COMMITTED --> 读已提交
允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生

ISOLATION_REPEATABLE_READ --> 可重复读
对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。

ISOLATION_SERIALIZABLE --> 序列化
最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,442评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,604评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,576评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,652评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,495评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,370评论 1 274
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,792评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,435评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,735评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,777评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,553评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,399评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,806评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,038评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,330评论 1 253
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,766评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,964评论 2 337

推荐阅读更多精彩内容