浅谈Spring的事务隔离级别与传播性

本文详细解释了数据库事务中的脏读、不可重复读和幻读现象,介绍了不同隔离级别的工作原理,特别关注了Spring中的事务管理和隔离级别设置,以及传播行为的区别。
摘要由CSDN通过智能技术生成

| 时间 | 事务1 | 事务2 | 备注 |

| — | — | — | — |

| 1 | 读取库存为1 | | |

| 2 | 扣减库存 | | 事务未提交 |

| 3 | | 读取库存为1 | |

| 4 | 提交事务 | | 库存变成0 |

| 5 | | 扣减库存 | 库存为0,无法扣减 |

不可重复读和脏读的区别是:脏读读取到的是未提交的数据,而不可重复读读到的确实已经提交的数据,但是违反了数据库事务一致性的要求。

一般来说,不可重复读的问题是可以接受的,因为其读到的是已经提交的数据,本身并不会带来很大的问题。因此,很多数据库如(ORACLE,SQL SERVER)将其默认隔离级别设置为READ COMMITTED,允许不可重复读的现象。

  • REPEATABLE READ (可重复读):可重复读的目标是为了克服READ COMMITED中出现的不可重复读,它指在同一个事务内的查询都是与事务开始时刻一致,以上表为例,在REPEATABLE READ隔离级别下它会发生如下变化:

| 时间 | 事务1 | 事务2 | 备注 |

| — | — | — | — |

| 1 | 读取库存为1 | | |

| 2 | 扣减库存 | | 事务未提交 |

| 3 | | 读取库存 | 不允许读取,等待事务1提交 |

| 4 | 提交事务 | | 库存变成0 |

| 5 | | 读取库存 | 库存为0,无法扣减 |

REPEATABLE READ虽然解决了不可重复读问题,但是他又会带来幻读问题,幻读是指,在一个事务中,第一次查询某条记录,发现没有,但是,当试图更新这条不存在的记录时,竟然能成功,并且,再次读取同一条记录,它就神奇地出现了。

| 时间 | 事务A | 事务2 | 备注 |

| — | — | — | — |

| 1 | begin | begin | |

| 2 | | 读取id为100的数据 | 没有数据 |

| 3 | 插入id为100的数据 | | |

| 4 | 提交事务 | | |

| 5 | | 读取id为100的数据 | 没有数据 |

| 6 | | 更新id为100的数据 | 成功 |

| 7 | | 读取id为100的数据 | 读取成功 |

| 8 | | 提交事务 | |

事务B在第2步第一次读取id=99的记录时,读到的记录为空,说明不存在id=99的记录。随后,事务A在第3步插入了一条id=99的记录并提交。事务B在第5步再次读取id=99的记录时,读到的记录仍然为空,但是,事务B在第6步试图更新这条不存在的记录时,竟然成功了,并且,事务B在第8步再次读取id=99的记录时,记录出现了。

  • SERIALIZABLE(串行化):数据库最高的隔离级别,它要求所有的SQL都会按照顺序执行,这样可以克服上述所有隔离出现的各种问题,能够完全包住数据的一致性。

Spring中配置隔离级别

在Spring项目中配置隔离级别只需要做如下操作

@Transactional(isolation = Isolation.SERIALIZABLE)

public int insertUser(User user){

return userDao.insertUser(user);

}

上面的代码中我们使用了串行化的隔离级别来包住数据的一致性,这使它将阻塞其他的事务进行并发,所以它只能运用在那些低并发而又需要保证数据一致性的场景下。

隔离级别字典:

DEFAULT(-1), ## 数据库默认级别

READ_UNCOMMITTED(1),

READ_COMMITTED(2),

REPEATABLE_READ(4),

SERIALIZABLE(8);

传播行为


在Spring中,当一个方法调用另外一个方法时,可以让事务采取不同的策略工作,如新建事务或者挂起当前事务等,这便是事务的传播行为。

定义

在Spring的事务机制中对数据库存在7种传播行为,通过枚举类Propagation定义。

public enum Propagation {

/**

  • 需要事务,默认传播性行为。

  • 如果当前存在事务,就沿用当前事务,否则新建一个事务运行子方法

*/

REQUIRED(0),

/**

  • 支持事务,如果当前存在事务,就沿用当前事务,

  • 如果不存在,则继续采用无事务的方式运行子方法

*/

SUPPORTS(1),

/**

  • 必须使用事务,如果当前没有事务,抛出异常

  • 如果存在当前事务,就沿用当前事务

*/

MANDATORY(2),

/**

  • 无论当前事务是否存在,都会创建新事务允许方法

  • 这样新事务就可以拥有新的锁和隔离级别等特性,与当前事务相互独立

*/

REQUIRES_NEW(3),

/**

  • 不支持事务,当前存在事务时,将挂起事务,运行方法

*/

NOT_SUPPORTED(4),

/**

  • 不支持事务,如果当前方法存在事务,将抛出异常,否则继续使用无事务机制运行

*/

NEVER(5),

/**

  • 在当前方法调用子方法时,如果子方法发生异常

  • 只回滚子方法执行过的SQL,而不回滚当前方法的事务

*/

NESTED(6);

}

日常开发中基本只会使用到REQUIRED(0),REQUIRES_NEW(3),NESTED(6)三种。

NESTEDREQUIRES_NEW是有区别的。NESTED传播行为会沿用当前事务的隔离级别和锁等特性,而REQUIRES_NEW则可以拥有自己独立的隔离级别和锁等特性。

NESTED的实现主要依赖于数据库的保存点(SAVEPOINT)技术,SAVEPOINT记录了一个保存点,可以通过ROLLBACK TO SAVEPOINT来回滚到某个保存点。如果数据库支持保存点技术时就启用保存点技术;如果不支持就会新建一个事务去执行代码,也就相当于REQUIRES_NEW

Transactional自调用失效

如果一个类中自身方法的调用,我们称之为自调用。如一个订单业务实现类OrderServiceImpl中有methodA方法调用了自身类的methodB方法就是自调用,如:

@Transactional

public void methodA(){

for (int i = 0; i < 10; i ) {

methodB();

}

}

@Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRES_NEW)

public int methodB(){

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

面试结束复盘查漏补缺

每次面试都是检验自己知识与技术实力的一次机会,面试结束后建议大家及时总结复盘,查漏补缺,然后有针对性地进行学习,既能提高下一场面试的成功概率,还能增加自己的技术知识栈储备,可谓是一举两得。

以下最新总结的阿里P6资深Java必考题范围和答案,包含最全MySQL、Redis、Java并发编程等等面试题和答案,用于参考~

重要的事说三遍,关注+关注+关注!

历经30天,说说我的支付宝4面+美团4面+拼多多四面,侥幸全获Offer

image.png

更多笔记分享

历经30天,说说我的支付宝4面+美团4面+拼多多四面,侥幸全获Offer

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
程等等面试题和答案,用于参考~

重要的事说三遍,关注+关注+关注!

[外链图片转存中…(img-wTKeGuVa-1713743590674)]

[外链图片转存中…(img-L2u4WfPK-1713743590674)]

更多笔记分享

[外链图片转存中…(img-qvO7zBx0-1713743590674)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 13
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
事务隔离级别是指多个事务并发执行时,一个事务对其他事务的可见和影响程度的控制。Spring框架支持四个事务隔离级别: 1. 未提交读(READ UNCOMMITTED):最低级别,一个事务可以读取未提交的数据,会导致脏读,不可重复读和幻读问题的出现。 2. 提交读(READ COMMITTED):一个事务只能读取已提交的数据,可以避免脏读问题,但可能导致不可重复读和幻读问题。 3. 可重复读(REPEATABLE READ):在一个事务中多次读取同一数据时,结果保持一致,避免了不可重复读问题。但仍然可能存在幻读问题。 4. 串行化(SERIALIZABLE):最高级别,通过确保事务串行执行来避免脏读、不可重复读和幻读问题。但会降低并发能。 传播机制是指在调用多个事务方法时,如何处理事务传播Spring框架提供七种传播行为: 1. REQUIRED:如果当前没有事务,就创建一个新事务;如果已存在事务,则加入该事务。 2. SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方法执行。 3. MANDATORY:强制要求存在当前事务,如果没有事务就抛出异常。 4. REQUIRES_NEW:创建一个新事务,并暂停当前事务(如果有)。 5. NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则将其挂起。 6. NEVER:以非事务方式执行操作,如果当前存在事务,则抛出异常。 7. NESTED:在当前事务的控制下执行一个嵌套事务,如果不存在当前事务,则创建一个新事务。嵌套事务可以独立提交或回滚,但在外部事务提交时才会生效。 通过选择合适的事务隔离级别传播机制,可以确保事务的数据一致、安全能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值