Java分布式解决方案(二)

news2024/12/23 18:35:23

文章目录

    • 🔥分布式事务处理_认识本地事务
    • 🔥关系型数据库事务基础_并发事务带来的问题
    • 🔥关系型数据库事务基础_MySQL事务隔离级别
    • 🔥MySQL事务隔离级别_模拟异常发生之脏读
    • 🔥MySQL事务隔离级别_模拟异常发生之不可重复读
    • 🔥MySQL事务隔离级别_模拟异常发生之幻读

🔥分布式事务处理_认识本地事务

在这里插入图片描述

什么是事务
事务就是针对数据库的一组操作,它可以由一条或多条SQL语句组成,同一个事务的操作具备同步的特点,事务中的语句要么都执行,要么都不执行。

举个例子:
你去小卖铺买东西,一手交钱,一手交货就是一个事务的例子,交钱和交货必须全部成功,事务才算成功,任一个活动失败,事务将撤销所有已成功的活动。

什么是本地事物
在计算机系统中,更多的是通过关系型数据库来控制事务,这是利用数据库本身的事务特性来实现的,因此叫数据库事务,由于应用主要靠关系数据库来控制事务,而数据库通常和应用在同一个服务器,所以基于关系型数据库的事务又被称为本地事务。
在这里插入图片描述

注:
⭐Business∶我们具体的业务代码
⭐Storage∶ 库存业务代码;扣库存
⭐Order∶订单业务代码;保存订单
⭐Account∶账号业务代码;减账户余额

数据库事务的四大特性ACID
在这里插入图片描述
数据库事务在实现时会将一次事务涉及的所有操作全部纳入到一个不可分割的执行单元,该执行单元中的所有操作要么都成功,要么都失败,只要其中任一操作执行失败,都将导致整个事务的回滚。

🔥关系型数据库事务基础_并发事务带来的问题

在这里插入图片描述

并发事务带来的问题
数据库一般会并发执行多个事务,而多个事务可能会并发地对相同的数据进行增加、删除、修改和查询操作,进而导致并发事务问题。
在这里插入图片描述

脏写
当两个或两个以上的事务选择数据库中的同一行数据,并基于最初选定的值更新该行数据时,因为每个事务之间都无法感知彼此的存在,所以会出现最后的更新操作覆盖之前由其他事务完成的更新操作的情况。也就是说,对于同一行数据,一个事务对该行数据的更新操作覆盖了其他事务对该行数据的更新操作。
在这里插入图片描述

解决方案:
让每个事物按照顺序串行的方式执行,按照一定的顺序一次进行写操作。

脏读
一个事务正在对数据库中的一条记录进行修改操作,在这个事务完成并提交之前,当有另一个事务来读取正在修改的这条数据记录时,如果没有对这两个事务进行控制,则第二个事务就会读取到没有被提交的脏数据,并根据这些脏数据做进一步的处理,此时就会产生未提交的数据依赖关系。我们通常把这种现象称为脏读,也就是一个事务读取了另一个事务未提交的数据。
在这里插入图片描述
解决方案:
先写后读,也就是写完之后再读。

不可重复读
一个事务读取了某些数据,在一段时间后,这个事务再次读取之前读过的数据,此时发现读取的数据发生了变化,或者其中的某些记录已经被删除,这种现象就叫作不可重复读。
在这里插入图片描述
解决方案:
先读后写,也就是读完之后再写。

幻读
一个事务按照相同的查询条件重新读取之前读过的数据,此时发现其他事务插入了满足当前事务查询条件的新数据,这种现象叫作幻读。
在这里插入图片描述

解决方案:
先读后写,也就是读完之后再写。

🔥关系型数据库事务基础_MySQL事务隔离级别

在这里插入图片描述

MySQL中的InnoDB储存引擎提供SQL标准所描述的4种事务隔离级别,分别为读未提交 (Read Uncommitted)、读已提交(ReadCommitted)、可重复读(Repeatable Read)和串行化(Serializable)。
在这里插入图片描述

读未提交(Read Uncommitted):事务可以读取未提交的数据,也称作脏读(Dirty Read)。一般很少使用。
读已提交(Read Committed):是大都是 DBMS (如:Oracle, SQLServer)默认事务隔离。执行两次同意的查询却有不同的结果,也叫不可重复读。
可重复读(Repeable Read):是 MySQL 默认事务隔离级别。能确保同一事务多次读取同一数据的结果是一致的。可以解决脏读的问题,但理论上无法解决幻读(Phantom Read)的问题。
可串行化(Serializable):是最高的隔离级别。强制事务串行执行,会在读取的每一行数据上加锁,这样虽然能避免幻读的问题,但也可能导致大量的超时和锁争用的问题。很少会应用到这种级别,只有在非常需要确保数据的一致性且可以接受没有并发的应用场景下才会考虑。

🔥MySQL事务隔离级别_模拟异常发生之脏读

在这里插入图片描述

前置知识

# 查看 MySQL 版本
select version();
# 开启事务
start transaction;
# 提交事务
commit;
# 回滚事务
rollback;

查看连接的客户端详情
每个 MySQL 命令行窗口就是一个 MySQL 客户端,每个客户端都可以单独设置(不同的)事务隔离级别,这也是演示 MySQL 并发事务的基础。

show processlist;

在这里插入图片描述

新建数据库和测试数据

-- 创建数据库
drop database if exists testdb;
create database testdb;
use testdb;
-- 创建表
create table userinfo(
 id int primary key auto_increment,
 name varchar(250) not null,
 balance decimal(10,2) not null default 0
);
-- 插入测试数据
insert into userinfo(id,name,balance)
values(1,'Java',100),(2,'MySQL',200);

查询事务的隔离级别

select
@@global.transaction_isolation,@@transaction_is
olation;

设置客户端的事务隔离级别
通过以下 SQL 可以设置当前客户端的事务隔离级别:

set session transaction isolation level 事务隔离
级别;

事务隔离级别的值有 4 个:
⭐READ UNCOMMITTED:读未提交
⭐READ COMMITTED:读已提交
⭐REPEATABLE READ:可重复读
⭐SERIALIZABLE:串行化

脏读
一个事务读到另外一个事务还没有提交的数据,称之为脏读。脏读演示的执行流程如下:
在这里插入图片描述

脏读演示步骤1
设置窗口 2 的事务隔离级别为读未提交,设置命令如下:

set session transaction isolation level read
uncommitted;

在这里插入图片描述

注意:
事务隔离级别读未提交存在脏读的问题。

脏读演示步骤2
窗口2开启事务,查询用户表如下图所示:

start transaction;
select * from userinfo;

在这里插入图片描述

注意:
从上述结果可以看出,在窗口 2 中读取到了窗口 1 中事务未提交的数据,这就是脏读。

脏读演示步骤3
在窗口 1 中开启一个事务,并给 Java 账户加 50 元,但不提交事务,执行的 SQL 如下:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> update userinfo set balance=balance+50
where name="java";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

在这里插入图片描述

脏读演示步骤4
在窗口 2 中再次查询用户列表,执行结果如下:
在这里插入图片描述

注意:
从上述结果可以看出,在窗口 2 中读取到了窗口 1 中事务未提交的数据,这就是脏读。

🔥MySQL事务隔离级别_模拟异常发生之不可重复读

不可重复读是指一个事务先后执行同一条 SQL,但两次读取到的数据不同,就是不可重复读。不可重复读演示的执行流程如下:
在这里插入图片描述

不可重复读演示步骤1
设置窗口 2 的事务隔离级别为读已提交

set session transaction isolation level read
committed;

在这里插入图片描述

注意:
读已提交可以解决脏读的问题,但存在不可重复读的问题。

不可重复读演示步骤2
在窗口 2 中开启事务,并查询用户表,执行结果如下
在这里插入图片描述

不可重复读演示步骤3

在窗口 1 中开启事务,并给 Java 用户添加 20 元,但不提交事务,再观察窗口 2 中有没有脏读的问题,具体执行结果如下图所示:
在这里插入图片描述

从上述结果可以看出,当把窗口的事务隔离级别设置为读已提交,已经不存在脏读问题了。接下来在窗口 1 中提交事务,执行结果如下图所示:
在这里插入图片描述

不可重复读演示步骤4
切换到窗口 2 中再次查询用户列表,执行结果如下:
在这里插入图片描述

不可重复读和脏读的区别:
脏读可以读到其他事务中未提交的数据,而不可重复读是读取到了其他事务已经提交的数据,但前后两次读取的结果不同。

🔥MySQL事务隔离级别_模拟异常发生之幻读

幻读名如其文,它就像发生了某种幻觉一样,在一个事务中明明没有查到主键为 X 的数据,但主键为 X 的数据就是插入不进去,就像某种幻觉一样。幻读演示的执行流程如下:
在这里插入图片描述

幻读演示步骤1
在窗口1和窗口2修改事务隔离级别为可重复读。

set session transaction isolation level
repeatable read;

幻读演示步骤2
设置窗口 2 为可重复读,可重复有幻读的问题,查询编号为 3 的用户,具体执行 SQL 如下:

start transaction;
select * from userinfo where id=3;

在这里插入图片描述

注意:
从上述结果可以看出,查询的结果中 id=3 的数据为空。

幻读演示步骤3
开启窗口 1 的事务,插入用户编号为 3 的数据,然后成功提交事务,执行 SQL 如下:

start transaction;
insert into userinfo(id,name,balance)
values(3,'Spring',100);
commit;

在这里插入图片描述

幻读演示步骤4
在窗口 2 中插入用户编号为 3 的数据,执行 SQL 如下:

insert into userinfo(id,name,balance)
values(3,'Spring',100);

在这里插入图片描述

注意:
添加用户数据失败,提示表中已经存在了编号为 3 的数据,且此字段为主键,不能添加多个。

幻读演示步骤5
在窗口 2 中,重新执行查询:

select * from userinfo where id=3;

在这里插入图片描述

注意:
在此事务中查询明明没有编号为 3 的用户,但插入的时候却却提示已经存在了,这就是幻读。

不可重复读和幻读的区别

二者描述的则重点不同,不可重复读描述的侧重点是修改操作,而幻读描述的侧重点是添加和删除操作。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浏览器渲染原理

阶段 - Parse 1、解析HTML,浏览器将从服务器获取到的HTML文件之后,会产生一个渲染任务,交给消息队列(EventLoop/MessageLoop)。 2、在事件循环机制的作用下,会将渲染任务交给主线程 3、主线程在获取到渲染…

入门vue(1-10)

正确学习方式&#xff1a;视频->动手实操->压缩提取->记录表述 1基础结构 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"&…

LeetCode 1599. 经营摩天轮的最大利润

【LetMeFly】1599.经营摩天轮的最大利润 力扣题目链接&#xff1a;https://leetcode.cn/problems/maximum-profit-of-operating-a-centennial-wheel/ 你正在经营一座摩天轮&#xff0c;该摩天轮共有 4 个座舱 &#xff0c;每个座舱 最多可以容纳 4 位游客 。你可以 逆时针 轮…

0103深度优先搜索和单点连通-无向图-数据结构和算法(Java)

文章目录1.1 走迷宫1.2 图的深度优先搜索实现1.3 算法分析及性能1. 4 单点连通性后记1.1 走迷宫 简单的迷宫&#xff0c;如下图1.1-1所示&#xff1a; 探索迷宫而不迷路&#xff0c;我们需要&#xff1a; 选择一条没有标记过的通道&#xff0c;在你走过的路上铺一条绳子&…

基于linux 实现DNS Client请求

DNS是什么&#xff1a; DNS是域名系统,Domain Name System的缩写,是一个服务。 作用&#xff1a; DNS就是把域名解析为IP地址&#xff0c;提供我们上网&#xff0c;我们能够上网最终是找到IP地址。 DNS请求报文格式&#xff1a; 分别包含 Transaction ID&#xff1a;会话标…

Linux环境开发stm32+vscode编码+gcc-arm编译+openocd烧录

文章目录Linux环境下STM32开发1前言2环境搭建3点灯&#xff1a;脚本方式命令行操作方式具体见参考2vscode将以上命令集成起来4总结Linux环境下STM32开发 1前言 最近在使用Keil开发STM32的时候总感觉代码写起来很很费劲&#xff0c;然后打算用vscode试试&#xff0c;刚开始用的…

js作用域和作用域链

1、局部作用域分为函数作用域和块作用域 1.1、函数作用域: 在函数内部声明的变量只能在函数内部被访问&#xff0c;外部无法直接访问。 总结 1.函数内部声明的变量&#xff0c;在函数外部无法被访问 2.函数的参数也是函数内部的局部变量 3.不同函数内部声明的变量无法互相访…

iscsi windows使用教程与smb das 区别

介绍——为什么不用smb而用iscsi 历史 说到SAN等传统存储设备&#xff0c;我们不得不提到SCSI&#xff0c;SCSI作为外部块设备的连接和传输协议&#xff0c;是最广泛的块设备协议&#xff0c;于1979首次提出&#xff0c;是为小型机研制的一种接口技术&#xff0c;现在已完全普…

taobao.item.joint.img( 商品关联子图 )

&#xffe5;开放平台免费API必须用户授权 关联一张商品图片到num_iid指定的商品中传入的num_iid所对应的商品必须属于当前会话的用户商品图片关联在卖家身份和图片来源上的限制&#xff0c;卖家要是B卖家或订购了多图服务才能关联图片&#xff0c;并且图片要来自于卖家自己的…

汇编指令学习(JMP、JE、JS、JP,JO,JB)

一、JMP无条件跳转不用看标志位&#xff0c;jmp后面跟一个内存地址&#xff0c;直接跳转到该地址jmp 0x0046B994二、JE&#xff08;JZ&#xff09;条件跳转当ZF标致为1的时候发生跳转&#xff0c;为0的时候不跳转&#xff0c;可以双击标志位&#xff0c;进行判断je 0x0046B99F三…

802.11 mac帧

mac帧格式帧格式MAC headFrame Control域Protocol VersionType和SubtypeTo DS和From DSMore FragmentsRetryPower ManagementMore DataProtected FrameOrderDuration/ID域Address域Address1 接收Address2 发送Address3 携带其他信息帮助mac帧传输Sequence Control域管理帧格式定…

vue3:生命周期(onErrorCaptured)

一、背景 当项目如果发生报错&#xff0c;影响程序体验。如果能以捕获的方式得到错误信息&#xff0c;而且还能定位问题&#xff0c;这样就好了&#xff0c;本文介绍onErrorCaptured实现我们想要的效果。 vue2&#xff1a;errorCaptured。使用与vue3同理。 vue3&#xff1a;…

某游戏app sig参数分析

今天要分析的app 叫 dGFwdGFwIDIuMjA= (base64 解码),来一起学习下。 找个视频接口,上来先抓个包,没错今天就是要分析下这个sig参数。 这个app 在高版本上有加固壳,并且还有frida检测(ps:遇到困难不会放弃,以后慢慢研究),这里只是研究sig参数,所以采用低版本了。 把…

ARM uboot 的移植2-从三星官方 uboot 开始移植

一、inand 驱动问题的解决 1、先从现象出发定位问题 (1) 解决问题的第一步&#xff0c;是定位问题。所谓定位问题&#xff0c;就是找到源代码当中导致这个问题的那一句或者那几句代码。有时候解决这个问题需要修改的代码和直接导致这个问题的代码是不同的。我们这里说的定位问…

一文深入分析虚拟机中对象锁实现!

一、前言 编程过程中经常会遇到线程的同步问题&#xff0c;Java 中对同步问题的解决方案比较多&#xff08;synchronized、JUC、原子操作、volatile、条件变量等&#xff09;&#xff0c;其中synchronized 最方便、简单易用&#xff0c;也是java 编程中使用最多的临界区保护方…

接口自动化入门-TestNg

目录1.TestNg介绍2、TestNG安装3、TestNG使用3.1 编写测试用例脚本3.2 创建TestNG.xml文件&#xff08;1&#xff09;创建testng.xml文件&#xff08;2&#xff09;修改testng.xml4、测试报告生成1.TestNg介绍 TestNg是Java中开源的自动化测试框架&#xff0c;灵感来源于Junit…

CSAPP第九章 虚拟内存

理解虚拟内存的原因 本章前部分描述虚拟内存是如何工作的&#xff0c;后一部分描述应用程序如何使用和管理虚拟内存 物理和虚拟寻址 虚拟内存作为缓存的工具 页表 页命中 缺页 虚拟内存作为内存管理的工具 简化链接&#xff0c;简化加载&#xff0c;简化共享&#xff0c;简化…

K8s集群部署

#部署方式有多种&#xff0c;本文采用kubeadm组件的方式来部署K8s集群 安装要求&#xff1a; 至少三台主机内存最少2G&#xff0c;CPU2核集群网络互通可以访问外网禁止swap分区 环境说明: 系统&#xff1a;ubuntu22.04.1 版本信息&#xff1a;kubernetes&#xff1a;1.26.…

HashMap底层的实现原理

目录一、知识点回顾二、HashMap 的 put() 和 get() 的实现2.1 map.put(k, v) 实现原理2.2 map.get(k) 实现原理2.3 为何随机增删、查询效率都很高&#xff1f;2.4 为什么放在 HashMap 集合 key 部分的元素需要重写 equals 方法?2.5 HashMap总结2.6 JDK8 之后&#xff0c;HashM…

由点到面贯穿整个Java泛型理解

泛型概述 Java泛型(generics)是DK5中引入的一个新特性&#xff0c;泛型提供了编译时类型安全监测机制&#xff0c;该机制允许我们在编译时检测到非法的类型数据结构。 泛型的本质就是参数化类型&#xff0c;也就是所操作的数据类型被指定为一个参数。 如我们经常使用的Array…