【Spring Boot】掌握 Spring 事务:隔离级别与传播机制解读与应用

前言

🌟🌟本期讲解关于spring 事务传播机制介绍~~~

🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客

🔥 你的点赞就是小编不断更新的最大动力                                       

🎆那么废话不多说直接开整吧~~

目录

📚️1.事务的隔离级别

🚀1.1MySQL事务隔离级别

🚀1.2Spring事务隔离级别

📚️2.Spring事务传播机制

🚀2.1什么是事务的传播机制

🚀2.2事务隔离与传播的区别

🚀2.3事务的传播机制

🚀2.4事务传播机制代码演示

2.4.1REQUIRED

 2.4.2REQUIRES_NEW

2.4.3NEVER

2.4.4NESTED

🚀2.5NESTED和REQUIRED 区别

📚️3.总结

📚️1.事务的隔离级别

🚀1.1MySQL事务隔离级别

读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.

因为其他事务未提交的数据可能会发⽣回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数据称之为脏数据, 这个问题称之为脏读.(就是一个事务还没有写完,另一个事务就在读了

读提交(READ COMMITTED): 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据

该隔离级别不会有脏读的问题.但由于在事务的执⾏中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读

大致就是,事务A在写完后,B读了之后,A又再次修改了,那么B再次读之后,就会发现两次的结果不一样

可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同⼀事务多次查询的结果⼀致, 但是其他事务新插⼊的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.

⽐如此级别的事务正在执⾏时, 另⼀个事务成功的插⼊了某条数据, 但因为它每次查询的结果都是⼀样的, 所以会导致查询不到这条数据, ⾃⼰重复插⼊时⼜失败(因为唯⼀约束的原因). 明明在事务中查询不到这条信息,但⾃⼰就是插⼊不进去, 这个现象叫幻读

串⾏化(SERIALIZABLE): 序列化, 事务最⾼隔离级别. 它会强制事务排序, 使之不会发⽣冲突, 从⽽解决了脏读, 不可重复读和幻读问题, 但因为执⾏效率低, 所以真正使⽤的场景并不多 

🚀1.2Spring事务隔离级别

Spring 中事务隔离级别有5 种:

1. Isolation.DEFAULT : 以连接的数据库的事务隔离级别为主.
2. Isolation.READ_UNCOMMITTED : 读未提交, 对应SQL标准中 READ UNCOMMITTED
3. Isolation.READ_COMMITTED : 读已提交,对应SQL标准中 READ COMMITTED
4. Isolation.REPEATABLE_READ : 可重复读, 对应SQL标准中 REPEATABLE READ
5. Isolation.SERIALIZABLE : 串⾏化, 对应SQL标准中 SERIALIZABLE

设置事务的隔离级别代码如下:

 @Transactional(rollbackFor = Exception.class, isolation = Isolation.DEFAULT)//设置所有回滚异常类型@RequestMapping("/r7")public Boolean r7(String userName, String password) throws IOException {Integer result = userService.registUser(userName, password);System.out.println("插入用户表, result: "+ result);if (true){throw new IOException();}return true;}

解释:

在代码中,注解里的参数rollbackfor指定所有异常都需要进行回滚,然后isolation指定是与数据库的事务隔离级别是一致的,那么这里的spring事务的隔离级别就是可重复读;

📚️2.Spring事务传播机制

🚀2.1什么是事务的传播机制

事务传播机制就是: 多个事务⽅法存在调⽤关系时, 事务是如何在这些⽅法间进⾏传播的

就比如,两个方法,都被transaction修饰了,假如这里的两个方法存在调用的关系,那么这里的事务是如何进行传播的,是使用A的事务,还是使用B的事务呢?

🚀2.2事务隔离与传播的区别

事务隔离级别解决的是多个事务同时调⽤⼀个数据库的问题

如下图:

⽽事务传播机制解决的是⼀个事务在多个节点(⽅法)中传递的问题

🚀2.3事务的传播机制

@Transactional 注解⽀持事务传播机制的设置, 通过 propagation 属性来指定传播⾏为.
Spring 事务传播机制有以下 7 种:

B是被调用的一方(service),A是调用的一方(controller)

1. Propagation.REQUIRED : 默认的事务传播级别. 如果当前存在事务, 则加⼊该事务. 如果当前没
有事务, 则创建⼀个新的事务.)

A有事务,B就直接使用A的事务,如果A没有事务,B创建一个事务

2. Propagation.SUPPORTS : 如果当前存在事务, 则加⼊该事务. 如果当前没有事务, 则以⾮事务的⽅式继续运⾏.

A有事务,B就直接使用A的事务,如果A没有事务,B以非事务的方式进行运行

3. Propagation.MANDATORY :强制性. 如果当前存在事务, 则加⼊该事务. 如果当前没有事务, 则
抛出异常.

A有事务,B就直接使用A的事务,如果A没有事务,那么就直接抛出异常

4. Propagation.REQUIRES_NEW : 创建⼀个新的事务. 如果当前存在事务, 则把当前事务挂起. 也
就是说不管外部⽅法是否开启事务, Propagation.REQUIRES_NEW 修饰的内部⽅法都会新开
启⾃⼰的事务, 且开启的事务相互独⽴, 互不⼲扰.

就是不管A有无事务,B都创建新的事务

5. Propagation.NOT_SUPPORTED : 以⾮事务⽅式运⾏, 如果当前存在事务, 则把当前事务挂起(不⽤).

就是不管A有无事务,B都直接以非事务的方式进行运行

6. Propagation.NEVER : 以⾮事务⽅式运⾏, 如果当前存在事务, 则抛出异常

如果A事务存在,那么就直接抛出异常

7. Propagation.NESTED : 如果当前存在事务, 则创建⼀个事务作为当前事务的嵌套事务来运⾏.
如果当前没有事务, 则该取值等价于 PROPAGATION_REQUIRED

没有事务就创建事务,有的话就干点其他的事情

🚀2.4事务传播机制代码演示

2.4.1REQUIRED

controller控制层,代表的A

@RequestMapping("/user")
@RestController
public class UserController2 {@Autowiredprivate UserService userService;@Autowiredprivate LogService logService;@Transactional(propagation = Propagation.REQUIRED)@RequestMapping("/p1")public String r3(String name, String password) {//⽤⼾注册userService.registUser(name, password);//记录操作⽇志logService.insertLog(name, "⽤⼾注册");return "p1";}
}

其余两个service:

登录日志打印:

@Service
public class LogService {@Autowiredprivate LogInfoMapper logInfoMapper;@Transactional(propagation = Propagation.REQUIRED)public void insertLog(String userName,String op){logInfoMapper.insert(userName,"用户注册");int a=10/0;}
}

user登录 :

@Service
public class UserService {@Autowiredprivate UserInfoMapper userInfoMapper;@Transactional(propagation = Propagation.REQUIRED)public Integer registUser(String userName, String password) {Integer result = userInfoMapper.insert(userName, password);return result;}
}

输出情况,打印的日志如下:

1. p1 ⽅法开始事务
2. ⽤⼾注册, 插⼊⼀条数据 (执⾏成功) (和p1 使⽤同⼀个事务)
3. 记录操作⽇志, 插⼊⼀条数据(出现异常, 执⾏失败) (和p1 使⽤同⼀个事务)
4. 因为步骤3出现异常, 事务回滚. 步骤2和3使⽤同⼀个事务, 所以步骤2的数据也回滚了. 

 2.4.2REQUIRES_NEW

我们将这里的两个service层改成REQUIRES_NEW

这里的其中一个事务进行了提交;

另一个代码存在算数异常的就没有进行提交

这里就是单独创建了自己的事务,这里的两个service层创建的两个事务就不会相互影响,所以其中一个提交,另一个进行了回滚的操作;

2.4.3NEVER

我们将其中一个代码传播机制改变

@Service
public class UserService {@Autowiredprivate UserInfoMapper userInfoMapper;@Transactional(propagation = Propagation.NEVER)public Integer registUser(String userName, String password) {Integer result = userInfoMapper.insert(userName, password);return result;}
}

 输出的日志如下所示:

那么这里可以看到报错信息就是A调用层存在事务,导致 报错;

2.4.4NESTED

将上述UserService 和LogService 中相关⽅法事务传播机制改为 Propagation.NESTED

小编这里就不演示代码了,大家可以自己去试一试;

打印日志如下:

由于是嵌套事务, LogService 出现异常之后, 往上找调⽤它的⽅法和事务, 所以⽤⼾注册也失败
了.最终结果是两个数据都没有添加
p1事务可以认为是⽗事务, 嵌套事务是⼦事务. ⽗事务出现异常, ⼦事务也会回滚, ⼦事务出现异常, 如果不进⾏处理, 也会导致⽗事务回滚(可以认为是REQUIRED,但是不完全是

🚀2.5NESTED和REQUIRED 区别

我们知道,当两个方法不存在问题时,这里的两种传播机制是没有啥区别的,但是当出现问题时,我们可以发现情况如上图所示,但是真的没有区别吗?答案是否定的;

@Service
public class LogService {@Autowiredprivate LogInfoMapper logInfoMapper;@Transactional(propagation = Propagation.NESTED)public void insertLog(String userName,String op){try {int a=10/0;}catch (Exception e){TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}logInfoMapper.insert(userName,"用户注册");   }
}

重新运⾏程序, 发现⽤⼾表数据添加成功, ⽇志表添加失败.


LogService 中的事务已经回滚, 但是嵌套事务不会回滚嵌套之前的事务, 也就是说嵌套事务可以实
现部分事务回滚

但是对于REQUIRED 如果回滚就是回滚所有事务, 不能实现部分事务的回滚. (因为属于同⼀个事务) 

嵌套事务之所以能够实现部分事务的回滚, 是因为事务中有⼀个保存点(savepoint)的概念, 嵌套事务进⼊之后相当于新建了⼀个保存点, ⽽滚回时只回滚到当前保存点.

 

这里是小编的理解,大家有问题或者质疑可以私信我哟~~~

📚️3.总结

💬💬本期讲解了关于MySQL事务的隔离级别回顾,以及spring的事务隔离级别以及事务传播机制,分别从概念和代码进行了演示~~~

🌅🌅🌅~~~~最后希望与诸君共勉,共同进步!!!


💪💪💪以上就是本期内容了, 感兴趣的话,就关注小编吧。

       😊😊  期待你的关注~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/4154.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【陕西省乡镇界】面图层shp格式arcgis数据乡镇名称和编码2020年wgs84坐标无偏移内容测评

标题中的“陕西省乡镇界面图层shp格式arcgis数据乡镇名称和编码2020年wgs84坐标无偏移.zip”表明这是一个地理信息系统(GIS)的数据集,专为陕西省的乡镇区域设计。该数据集以Shapefile(shp)格式提供,是GIS领…

国家统计局湖北调查总队副总队长张小青一行调研珈和科技农业遥感调查智能化算法

1月15日上午,国家统计局湖北调查总队党组成员、副总队长张小青一行莅临珈和科技开展调研。调研期间,张小青一行实地了解了珈和科技在自动化作物分布提取技术领域的最新成果,深入探讨了作物自动化处理模型在农业调查上应用的创新价值及优化方向…

-bash: /java: cannot execute binary file

在linux安装jdk报错 -bash: /java: cannot execute binary file 原因是jdk安装包和linux的不一致 程序员的面试宝典,一个免费的刷题平台

vue集成高德地图API实现坐标拾取功能

安装与配置: 组件 | vue-amapDescriptionhttps://elemefe.github.io/vue-amap/#/zh-cn/introduction/install简介 | vuemap/vue-amap简介https://vue-amap.guyixi.cn/zh-cn/introduction/introduction.html ​​​​我的应用 | 高德控制台高德开放平台官网控…

【大数据2025】Yarn 总结

分布式资源管理系统讲解总结 一、引言 围绕分布式资源管理系统展开,重点涵盖 Yarn 的简介、原理、资源调度策略以及运维和管理,旨在让学员全面掌握相关知识。Yet Another Resource Negotiator 二、Yarn 诞生背景 在 Hadoop 1.X 中仅有 HDFS 和 MapRe…

微服务学习:基础理论

一、微服务和应用现代化 1、时代的浪潮,企业的机遇和挑战 在互联网化数字化智能化全球化的当今社会,IT行业也面临新的挑战: 【快】业务需求如“滔滔江水连绵不绝”,企业需要更快的交付【变】林子大了,百色用户&…

python+django+Nacos实现配置动态更新-集中管理配置(实现mysql配置动态读取及动态更新)

一、docker-compose.yml 部署nacos服务 version: "3" services:mysql:container_name: mysql# 5.7image: mysql:5.7environment:# mysql root用户密码MYSQL_ROOT_PASSWORD: rootTZ: Asia/Shanghai# 初始化数据库(后续的初始化sql会在这个库执行)MYSQL_DATABASE: nac…

【专题二 二叉树中的深搜】98. 验证二叉搜索树

1.题目解析 2.讲解算法原理 二叉搜索树的中序遍历是一个有序序列 1.使用全局变量的优势 2.回溯 3.剪枝 左子树是二叉搜索树当前节点符合二叉搜索树的定义右子树是一个二叉搜索树 3.编写代码 /*** Definition for a binary tree node.* public class TreeNode {* in…

Reactor 模式在 Edis、Nginx 和 Netty 中的应用与高性能网络模式解析

文章目录 参考文章Reactor 模式在 Edis、Nginx 和 Netty 中的应用与高性能网络模式解析一、Reactor 模式二、Redis 中的 Reactor 模式三、Nginx 中的 Reactor 模式四、Netty 中的 Reactor 模式五、Reactor 模式的优势六、总结 参考文章 redis,nginx,net…

C++,设计模式,【目录篇】

文章目录 1. 简介2. 设计模式的分类2.1 创建型模式(Creational Patterns):2.2 结构型模式(Structural Patterns):2.3 行为型模式(Behavioral Patterns): 3. 使用设计模式…

深度学习 Pytorch 基本优化思想与最小二乘法

在正式开始进行神经网络建模之前,我们还需要掌握pytorch中最核心的基础数学工具——autograd(自动微分)模块。虽然对于任何一个通用的深度学习框架都会提供许多自动优化的算法和现成的loss function,但如果想更深入理解神经网络,对深度学习的…

word转pdf

依赖 先安装好MAVEN https://blog.csdn.net/m0_62214280/article/details/140643392 链接&#xff1a;https://pan.baidu.com/s/1jISO-TPEyLgC8RTmMJGRQw 提取码&#xff1a;9ju8 <dependency><groupId>com.aspose</groupId><artifactId>aspose-words…

【多线程】线程池

一、什么是线程池 线程池&#xff08;Thread Pool&#xff09;是一种多线程并发执行的设计模式&#xff0c;它通过维护一个线程集合来执行多个任务&#xff0c;避免频繁地创建和销毁线程&#xff0c;提高系统性能和响应速度。 就好比如你经营了一家餐饮店&#xff0c;你名下有…

【QT】: 初识 QWidget 控件 | QWidget 核心属性(API) | qrc 文件

&#x1f525; 目录 1. 控件概述 控件体系的发展阶段 2. QWidget 核心属性 2.1 核心属性概览2.2 用件可用&#xff08;Enabled&#xff09; 2.3 坐标系&#xff08;Geometry&#xff09; **实例 1: 控制按钮的位置**实例 2: 表白 程序 2.4 窗口标题&#xff08;windowTiltle&a…

CSS 合法颜色值

CSS 颜色 CSS 中的颜色可以通过以下方法指定&#xff1a; 十六进制颜色带透明度的十六进制颜色RGB 颜色RGBA 颜色HSL 颜色HSLA 颜色预定义/跨浏览器的颜色名称使用 currentcolor 关键字 十六进制颜色 用 #RRGGBB 规定十六进制颜色&#xff0c;其中 RR&#xff08;红色&…

C++第十五讲:异常

C第十五讲&#xff1a;异常 1.异常的概念和使用1.1异常的抛出和捕获1.2异常抛出和捕获的注意事项1.3异常的重新抛出1.4异常规范 2.标准库的异常 1.异常的概念和使用 1.1异常的抛出和捕获 异常的抛出和捕获的过程分为三个阶段&#xff1a; 1.异常的抛出&#xff1a; 使用throw对…

HTML<bdo>标签

例子 指定文本方向&#xff1a; <bdo dir"rtl"> This text will go right-to-left. </bdo> <!DOCTYPE html> <html> <body> <h1>The bdo element</h1> <p>This paragraph will go left-to-right.</p> …

Git:问题解决办法 及 Tips 总结

目录 查看历史记录及比较区别查看所有提交的历史记录查看提交的详细历史记录查看提交之间的差异点击文件操作历史&#xff0c;筛选出所有改动过此文件的提交任意两个提交之间的比较&#xff08;开发及查BUG常用&#xff09; 在需要版本回滚的情况下处理方法短时间内无法彻查BUG…

uniApp开通uniPush1.0个推,SpringBoot集成uniPush1.0个推

uniApp开通unipush1.0个推&#xff0c;SpringBoot程序集成 一、APP开通unipush1.0个推(商户App源码仅支持1.0个推) 1.app模块配置开通推送 2.应用开通推送 3.开通后点击消息推送菜单会看到如下页面 完成以上步骤后 此时android 仅支持在线推送。 4.配置各厂商离线推送 暂未…

[JavaScript] 深入理解流程控制结构

文章目录 1. **if-else 语句**基本语法&#xff1a;示例&#xff1a;扩展&#xff1a;else if 2. **switch-case 语句**基本语法&#xff1a;示例&#xff1a;注意事项&#xff1a; 3. **for 循环**基本语法&#xff1a;示例&#xff1a;扩展&#xff1a;for-in 和 for-of 4. *…