SpringBoot中级开发--事务配置管理(10)

2023-09-19 11:29:34

事务在整个开发框架中是一个非常常用的功能,特别涉及到数据库操作。像Mysql,就有4个数据库级别:

(1) READ UNCOMMITTED(读未提交):允许读取未提交的数据。这种级别的事务可以读取到其他事务未提交的数据,可能会导致脏读、不可重复读和幻读等问题。

(2)READ COMMITTED(读已提交):只能读取已经提交的数据。这种级别的事务可以避免脏读,但可能会出现不可重复读和幻读等问题。

(3)REPEATABLE READ(可重复读):保证在同一个事务中多次读取同一份数据时,得到的结果是一致的。这种级别的事务可以避免脏读和不可重复读,但可能会出现幻读等问题。

(4)SERIALIZABLE(串行化):强制事务串行执行,避免了所有并发问题。这种级别的事务可以避免所有并发问题,但可能会导致性能问题。

事务级别从低到高,性能越来越差。通过不同的应用场景,选择不同的事务。
(1) READ UNCOMMITTED(读未提交):对数据一致性要求不高的,比如 统计分析

(2)READ COMMITTED(读已提交):对数据一致性要求较高,比如,金融计费系统

(3)REPEATABLE READ(可重复读):对数据一致性要求非常高,比如银行

(4)SERIALIZABLE(串行化):对数据一致性要求最高,这个也是银行应用比较多

接下来我们介绍,脏读,不可重复读,幻像读,第一类更新丢失,第二类更新丢失

脏读

时间序转账事务甲取款事务乙
1开始事务
2开始事务
3查询到账户有100元
4取出50,余额修改为50元
5查询到余额为50元
6撤销事务,余额改回100元
7存入10元,余额为60元
8事务提交

发生在第5步的就是脏读,由于甲读到乙未有提交的数据,造成脏读,后面乙又撤回了事务,把本该取的50元退了回去,但是甲由于读到了脏数据,并且根据脏数据存入了10元,这样就造成了账户白白丢失了50元。

不可重复读

时间序取款事务甲转账事务乙
1开始事务
2开始事务
3查询到账户有100元
4查询到账户有100元
5取出10元,余额为90元
6提交事务
7查询余额为90元,与第4步的不一致

在同一个事务中,4,7时间序读出的余额都不一样。

幻像读

时间序统计事务甲转账事务乙
1开始事务
2开始事务
3统计总账户有100元
4现在增加一个账户,存入10元
5提交事务
6再次统计是110元

3,6查询出来的数据金额不一致。这样就出现了幻像读。幻像读和不可重复读感觉上好像一样,但是不可重复读是由于数据的更新造成的,要避免的话,直接加上行锁就可以。但是幻像读是由于数据新增造成的,对于这种问题,需要加上表锁。

第一类更新丢失

时间序取款事务甲转账事务乙
1开始事务
2开始事务
3查询到账户有100元
4查询到账户有100元
5汇入10元,余额为110元
6事务提交
7取出10元,把余额设为90元
8事务撤销
9余额恢复为100元(丢失更新)

甲在撤销事务的时候,把乙存入的10元给抹掉了。

第二类更新丢失

时间序转账事务甲取款事务乙
1开始事务
2开始事务
3查询到账户有100元
4查询到账户有100元
5取出10元,余额为90元
6事务提交
7存入10元
8事务提交
9把余额设为110元(丢失更新)

转账事务甲把取款业务乙的提交事务更新了,这样造成银行可能损失了10元。

Mysql的4个事务隔离级别能处理的业务并发

隔离级别脏读不可重复读幻象读第一类丢失更新第二类丢失更新
READ UNCOMMITTEDyesyesyesnoyes
READ COMMITTEDnoyesyesnoyes
REPEATABLE READnonoyesnono
SERIALIZABLEnonononono

在Springboot中,我们先引入事务依赖包,加入了mybatis这个依赖后,springboot就已经自动注入了DataSourceTransactionManager,这样就可以直接使用@Transactional 注解进行事务使用,Transactional 既可以注解在方法上,也可以注解在类上,注解在类上代表该类的public方法都开启事务的,如果类和方法都开启了Transactional ,类级别的注解会重载方法级的注解。
在这里插入图片描述
我们紧接上一篇的代码,在DAO层增加insert 代码

    @Insert("insert into welcome_info(info) values('transaction test')")
    @DS("test")
    public void  insertintoWelcomeinfo();

在Service层增加@Transactional注解,并且手动抛出异常

  @Transactional
    public void insertWelcomeInfo(){
        //插入一条记录
        welcomDao.insertintoWelcomeinfo();
        //手动抛出异常
        throw new RuntimeException();
    }

在Test用例代码中,增加测试用例方法,来测试上面的Service方法,看数据是否会回滚

    @Test
    void testTransactional(){
        welcomeService.insertWelcomeInfo();
    }

运行之后,会直接抛出异常,数据库并没有增加记录,这样异常就生效了。
在这里插入图片描述
现在如果我们注释掉throw new RuntimeException();这行代码,那么记录就会插入数据库。
在这里插入图片描述
有时候有些异常没有被捕获到,而造成事务没有回滚,这是由于Springboot的默认事务是遇到RuntimeException和程序错误Error造成事务回滚。如果要捕获这些通用的异常,只要在注解中增加rollbackfor选项。比如: @Transactional(rollbackFor = Exception.class)

我们来认识一下Transactional注解的主要配置选项

属性值具体意义
propagationtiong主要定义事务周期
isolation设置事务隔离级别
timeout指定事务过期时间,默认为数据库事务过期时间
readonly指定事务是否是只读事务
rollbackFor指定哪些异常可以引起事务回滚
noRollbackFor指定哪些异常不引起事务回滚

propagationtiong选项:

REQUIRED,方法A调用时没有事务就新建,当调用另一个方法B时,方法B将使用与A相同的事务,如果B发生异常,这个事务都回滚回去。

REQUIRES_NEW,方法A和B,在方法调用的时候无论是否有开启一个新事务,如方法B有异常不会导致方法A的数据回滚。

NESTED 和上面的类似,但支持JDBC,不支持JPA或Hibernate

SUPPORT 方法调用时有事物就用事务,没事务就不用事务

NOT SUPPORT 强制不在事务中执行,在方法调用到结束阶段事务都会被挂起

NEVER 强制方法不在事务中执行,若有事务抛出异常

MANDATORY 强制方法在事务中,没有事务就抛出异常

Isolation选项

READ UNCOMMITTED

READ COMMITTED

REPEATABLE_READ

SERIALIZABLE

DEFAULT 使用数据库的默认是隔离级别,ORACLE,SQL SERVER是READ COMMITTED ,Mysql是REPEATABLE_READ

程序的源码在这里可以下载到链接:链接: https://pan.baidu.com/s/1jL04s4huVnTBOaQyg68QIA 提取码: vgut

更多推荐

软件定制app开发方式与优势|小程序搭建

软件定制app开发方式与优势|小程序搭建目前软件定制app开发方式主要两种1、利用模板开发很多软件开发公司会以模板的方式出售,即现有的app功能和设计样式都是现成的,无需从零开始定制开发。优点:费用低,一般价格在几千到上万。快速上线,方便实惠;缺点:功能固定,难以修改。在此之前需要确定自己需要哪些功能,现有app模板是

小乌龟(TortoiseGit)连接GitLab

目录🍟写在前面🍟实验目标🍟安装gitlab🍿1、安装依赖🍿2、下载清华gitlab包🍿3、安装gitlab🍿4、修改配置文件🍿5、管理命令🍟访问gitlab🍟界面设置🍿修改语言🍿修改密码🍿创建项目🍟下载小乌龟安装包🍟配置ssh秘钥🍟Git目录设置🍟推送/拉取操作🦐博客主页:大虾好吃吗

【hive】行转列—explode()/posexplode()/lateral view 函数使用场景

文章目录一、lateralview函数二、explode()函数三、posexplode()函数四、行转列使用单列转多行多列转多行一、lateralview函数功能:用于和UDTF函数(explode,split)结合使用,把某一行数据拆分成多行数据,再将多行结果组合成一个支持别名的虚拟表。主要解决select使用UD

华为云云耀云服务器L实例评测|使用华为云云耀云服务器L实例部署 GitLab Runner实现GitLab CI/CD,项目的DevOps

应用场景GitLabRunner介绍GitLabRunner是一个用于执行GitLabCI/CD任务的工具,它可以在Linux、macOS和Windows上使用,并且可以通过包管理器、二进制文件或Docker镜像进行安装。它与GitLabCI结合使用,能够在最少的手动干预下帮助团队实现CI/CD流程的自动化。GitLa

《PostgreSQL中的JSON处理:技巧与应用》

🌷🍁博主猫头虎(🐅🐾)带您GotoNewWorld✨🍁🐅🐾猫头虎建议程序员必备技术栈一览表📖:🛠️全栈技术FullStack:📚MERN/MEAN/MEVNStack|🌐Jamstack|🌍GraphQL|🔁RESTfulAPI|⚡WebSockets|🔄CI/CD|🌐Git&Versio

靠差异化上了短剧“牌桌”后,百度准备怎么做生态?

从最初的野蛮生长到如今的百花齐放,短剧市场已然进入了质量与创意的竞争。据《中国网络视听发展研究报告》数据显示,行业内重点网络微短剧上线数量从2021年的58部,飙升到2022年的172部。相比起前几年处于风口时的爆发式增长,“分账走低、竞争激烈、流量下滑”成为当下短剧市场的关键词。回顾近两年短剧赛道的发展,“古风”“霸

想要精通算法和SQL的成长之路 - 戳气球

想要精通算法和SQL的成长之路-戳气球前言一.戳气球1.1记忆化搜索前言想要精通算法和SQL的成长之路-系列导航一.戳气球原题链接首先我们看一下题干:对于超出了数组边界的,就当做它是一个数字为1的气球。遇到这种的,我们可以考虑给数组边界添加哨兵。其值为1。//左右各加一个哨兵节点publicintmaxCoins(in

spring boot+redis整合基础入门

文章目录前言准备依赖项配置文件redis模板类注入设置序列化方式实施基础字符串操作、超时设置Hash操作hash的使用场景以及优缺点列表操作列表操作的应用场景以及优缺点Set的基础操作Set类型的业务场景以及优缺点Demo地址总结前言最近项目中有用到redis进行一些数据的缓存,于是就想写一篇springboot集成r

Java版企业电子招标采购系统源码Spring Cloud + Spring Boot +二次开发+ MybatisPlus + Redis

项目说明随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及审计监督要求;通过电子化平台提高招投标工作的公开性和透明性;通过电子化招投标,使得招标采购的质量更高、速度

Java线程池ThreadPoolExecutor应用(Spring Boot微服务)

记录:475场景:在SpringBoot微服务中使用Java线程池ThreadPoolExecutor。实现Runnable接口提交线程任务到线程池。版本:JDK1.8,SpringBoot2.6.3。1.使用注解配置线程池ThreadPoolExecutor(1)说明ThreadPoolExecutor,全称:jav

RIS 系列 Semantics-Aware Dynamic Localization and Refinement for Referring Image Segmentation 论文阅读笔记

RIS系列Semantics-AwareDynamicLocalizationandRefinementforReferringImageSegmentation论文阅读笔记一、Abstract二、引言三、相关工作ReferringimagesegmentationDynamicconvolutionMulti-mod

热文推荐