【数据库】事务、事务并发问题、并发事务隔离级别、及sql演示

news2024/11/20 10:40:12

文章目录

  • 一、事务
    • 1.1 事务简介 及 sql 操作
    • 1.2 事务的特性
  • 二、事务并发问题
  • 三、事务隔离级别
  • 四、sql 演示
    • 4.1 脏读
    • 4.2 不可重复读
    • 4.3 幻读
  • 五、演示代码


一、事务

1.1 事务简介 及 sql 操作

事务:数据库执行的一系列操作,这些操作要么全部执行,要么全部不执行
若要把多个操作放在一个事务范围内,需要手动 开启事务,提交事务,回滚事务

-- 查询事务提交方式
select @@autocommit;		-- 1. 自动提交,0. 手动提交
-- 设置事务手动提交
set @@autocommit = 0;
-- 提交事务
commit;
-- 回滚事务
rollback;
-- 开启事务
start transaction;	# 方式 1
begin;				# 方式 2

1.2 事务的特性

  • 原子性(Atomicity):事物是一组不可分割的最小操作单元。要么全部成功,要么全部失败
  • 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态
  • 隔离性(Isolation):事物在不受外部并发操作影响的独立环境下运行
  • 持久性(Durability):事务一旦提交或回滚,对数据库中的数据改变是永久的

二、事务并发问题

  1. 脏读一个事务读到另一个事务还没提交的数据
  2. 不可重复读一个事务先后读取同一条记录,但两读读取的数据不一致
  3. 幻读一个事务按条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据存在

假设有事务A、事务B、表 tb

脏读:    
        A 修改 tb 中的数据,但是还没有提交(commit)
        B 读 tb 中的数据,读到了未提交的数据

事务的操作只有提交了才会生效,刷新到磁盘中。由于事务A还没有提交,A的修改只写入了缓冲池,此时B读到了A修改的缓冲池的数据,读到了 “脏东西”。因为 A 不一定会提交,有可能是错误数据最后 rollback 回滚。


不可重复读:    
        A 先读了一条记录,发现是(1,2,3,4,5)
        B 修改了该条记录,改为(a,b,c,d,e)
        B 提交(commit)
        A 第二次读该记录,发现是(a,b,c,d,e)

重点看事务  A ,在同一个事务中先后读取同一条记录,但是两次读到的数据不一致
注意,B 执行了 commit。如果 B 没有执行 commit,那是脏读


幻读
        1. A 先读一条记录,发现没有该记录
        2. B 插入该记录,并提交
        3. A 尝试插入一条记录,发现插入不进去,存在该记录
        4. A 再次查询该记录,发现还是不存在

B 插入了该记录,并提交。那么 A 能查到该记录吗?
不能。如果 A 能查到该记录,那么 1 3 步骤查到的数据肯定不一样,这叫什么?这叫不可重复读。这点也是不可重复读和幻读的第 1 个区别

B 插入了该记录,并提交。那么 A 能插入该记录吗?
也不能。。。比如主键唯一,unique

幻读是针对 insert 插入语句,不可重复读针对 update 和 delete 语句。这是不可重复读和幻读的第 2 个区别

查询查不到,插入又显示已经存在。就像出现幻觉了一样


三、事务隔离级别

隔离级别脏读不可重复读幻读
read uncommitted111
read committed(oracle 默认)011
repeatable read(mysql 默认)001
serializable000

1 表示在该隔离级别下会出现该种问题,0反之
事务的隔离级别越低,并发能力越高,越容易出现问题

-- 查看事务隔离级别
select @@transaction_isolation;
-- 设置事务隔离级别
set session|global transaction isolation level xxx;	# xxx 为隔离级别
# global 对全局隔离级别生效,后面获取的连接都会生效
# session 仅对当前会话生效

read uncommitted (读未提交)。这种隔离级别会读到未提交的数据,会出现脏读问题
read committed(读已提交)。读已提交的数据,如果 B 在 A 事务过程中提交,A 会在一个事务中读一条记录,两次查询结果不同,会出现不可重复读问题
repeatable read(可重复读)。在一个事务 A 中,无论 B 是否提交改变,A 查询到的结果在事务 A 中都是相同的。但是如果 B 插入并提交,A 就无法插入。查询不存在,插入显示存在,会出现幻读问题
serializable(序列化)。如果 A 查询记录不存在,B 打算插入,B 会被阻塞。等 A 提交后 B 才会继续执行,避免幻读问题

四、sql 演示

4.1 脏读

  1. 先创建一张银行帐户表,往里面添加用户。左边为事务 A ,右边事务 B
    在这里插入图片描述
    在这里插入图片描述
  2. 设置两个事务,提交类型为手动提交,事务隔离级别为 read uncommitted,开启事务。以下操作在注释中,用1. 2. 3. 表示代码执行过程
    在这里插入图片描述
    事务 A 查询到了 事务 B 未提交的数据。张三并没有真的扣去1000元。该事务还没提交,可能 rollback 回滚了,对吧?

解决办法是,把事务的隔离级别设置为 read committed
在这里插入图片描述


4.2 不可重复读

read committed 下会出现不可重复读的问题
在这里插入图片描述
解决办法是,把事务的隔离级别设置为 repeatable read
在这里插入图片描述


4.3 幻读

repeatable read 下会出现幻读问题
在这里插入图片描述
== serializable== 解决幻读问题
在这里插入图片描述
由于 A 已经查询过记录,所以 当B尝试插入的时候,会被阻塞。等待 事务 A 提交后,B 才会继续执行。从而避免幻读的问题
注意,查询的是 id = 4,而不是姓名等于赵四。因为 id 是主键唯一,如果是赵四,无论 B 是否插入赵四,A都可以再插入一条名叫赵四的帐户,不会出现幻读


五、演示代码

事务a

CREATE DATABASE bank;
USE bank;
CREATE TABLE account (
    id INT PRIMARY KEY COMMENT 'id',
    name VARCHAR(20) COMMENT '姓名',
    money DECIMAL(12, 2) COMMENT '帐户余额'
) COMMENT '帐户表';
INSERT INTO account (id, name, money) values
                    (1, '张三', 5000),
                    (2, '李四', 3000),
                    (3, '王五', 4000);
USE bank;
-- 事务 A
SET @@AUTOCOMMIT = 0;   # 设置手动提交
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ; # 事务隔离级别
START TRANSACTION ;     # 开启事务
# 1. A 先查询 account 表中,张三有多少钱
SELECT * FROM bank.account WHERE NAME = '张三' ;
            # 结果:1,张三,5000.00
# 3. A 再查 张三有多少钱
SELECT * FROM bank.account WHERE NAME = '张三' ;
            # 1,张三,4000.00
# 关闭事务
COMMIT;

-- read committed 解决 脏读问题
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED ;

# 1. A 先查询 account 表中,张三有多少钱
SELECT * FROM bank.account WHERE NAME = '张三' ;
            # 结果:1,张三,5000.00
# 3. A 再查 张三有多少钱
SELECT * FROM bank.account WHERE NAME = '张三' ;
            # 1,张三,5000.00,未读到 事务 B 中未提交的数据,无脏读问题
# 关闭事务
COMMIT;


-- read committed 下出现不可重复读的问题
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED ;
# 1. A 先查询 account 表中,张三有多少钱
SELECT * FROM bank.account WHERE NAME = '张三' ;
            # 结果:1,张三,5000.00
# 4. A 再查 张三有多少钱
SELECT * FROM bank.account WHERE NAME = '张三' ;
            # 1,张三,4000.00,读到 事务 B 中已提交的数据,出现不可重复读的问题
# 关闭事务
COMMIT;

-- repeatable read 解决不可重复读问题
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
# 1. A 先查询 account 表中,张三有多少钱
SELECT * FROM bank.account WHERE NAME = '张三' ;
            # 结果:1,张三,5000.00
# 4. A 再查 张三有多少钱
SELECT * FROM bank.account WHERE NAME = '张三' ;
            # 1,张三,5000.00,未读到事务B中已提交的数据,未出现不可重复读的问题
# 关闭事务
COMMIT;


-- repeatable read 出现幻读问题
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;

START TRANSACTION ;
# 1. A 先查询用户 4 是否存在
SELECT * FROM account WHERE id = 4;
            # 查询结果为空
# 4. A 向表中添加用户4
INSERT INTO account (id, name, money) value
                    (4, '赵四', 0);
            # 报错,已存在该用户
# [2023-06-24 20:33:06] [23000][1062]
# Duplicate entry '4' for key 'account.PRIMARY'
COMMIT ;

-- serializable 解决幻读问题
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE ;
START TRANSACTION ;
# 1. A 先查询 id 为 4 的用户是否存在
SELECT * FROM account WHERE id = 4;
            # 查询结果为空
# 4. A 向表中添加用户赵四, 添加成功
INSERT INTO account (id, name, money) value
                    (4, '赵四', 0);
# 15 A 再次查询用户 赵四 是否存在
SELECT * FROM account WHERE id = 4;
            # 查询成功
COMMIT ;

事务b

USE bank;
-- 事务 B
SET @@AUTOCOMMIT = 0;   # 设置手动提交
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ; # 事务隔离级别
START TRANSACTION ;     # 开启事务
# 2. B 从张三帐户中扣去 1000 元,转移到李四的帐户
UPDATE bank.account SET money = money - 1000 WHERE NAME = '张三' ;
# 关闭事务,撤回扣钱操作
ROLLBACK;

-- read committed 解决 脏读问题
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED ;

START TRANSACTION ;     # 开启事务
# 2. B 从张三帐户中扣去 1000 元,转移到李四的帐户
UPDATE bank.account SET money = money - 1000 WHERE NAME = '张三' ;
# 关闭事务,撤回扣钱操作
ROLLBACK;


-- read committed 下出现不可重复读的问题
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED ;
# 2. B 从张三帐户中扣去 1000 元,转移到李四的帐户
UPDATE bank.account SET money = money - 1000 WHERE NAME = '张三' ;
# 3. 提交事务,确认扣钱操作
COMMIT ;

# 把张三的钱恢复到 5000
UPDATE account SET money = money + 1000 WHERE NAME = '张三';

-- repeatable read 解决不可重复读问题
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
# 2. B 从张三帐户中扣去 1000 元,转移到李四的帐户
UPDATE bank.account SET money = money - 1000 WHERE NAME = '张三' ;
# 3. 提交事务,确认扣钱操作
COMMIT ;




-- repeatable read 出现幻读问题
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;

START TRANSACTION ;
# 2. B 向表中添加用户 4
INSERT INTO account (id, name, money) value
                    (4, '赵四', 0);
# 3. 提交
COMMIT;

# 删除用户 4
DELETE FROM account WHERE id = 4;



-- serializable 解决幻读问题
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE ;
START TRANSACTION ;
# 2. B 向表中添加用户 4
INSERT INTO account (id, name, money) value
                    (4, '赵四', 0);
        # 由于 A 查询过 用户4,B 被阻塞
# 3. 提交
COMMIT;

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

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

相关文章

【Java技术专题】「入门到精通系列教程」深入探索Java特性中并发编程体系的原理和实战开发指南(内存模型技术专题)

深入探索Java特性中并发编程体系的原理和实战开发指南( 线程进阶技术专题) 前言介绍JVM内存模型运行时数据区域堆内存栈内存 内存访问规则原子性对象类型基本类型 可见性有序性(Happen Before法则)系统内存(MESI协议&a…

【OS】【期末选择题】【2023春】【仅供参考】

文章目录 题型一、选择第一章(10)第二章(19)第三章(23)第四章(32)第五章(15)第六章(15) 二、填空题三、简答题1.信号量2.调度算法3.页面置换4.虚拟地址到物理地址的映射 Reference 题型 题型题量分值选择10%填空25%10%10%解答题210’大题215’ 一、选择 第一章(10) 操作系统…

HuggingFace-RL-Unit2-Part1——Q-learning算法介绍

Q-learning算法介绍 文章目录 Q-learning算法介绍回顾: 什么是RL? 两种基于价值的方法状态价值函数动作价值函数 贝尔曼方程:简化价值计算蒙特卡罗 VS 时序差分学习蒙特卡洛:在一个回合结束后进行学习时序差分算法:在每一步进行学习 学习进展…

定时器的实现原理

文章目录 1.定时器的作用?2.数据结构要求3.时间轮4.分级时间轮5.业界实现方案参考文献 1.定时器的作用? 定时器的主要用途是执行定时任务。 定时任务在很多场景都需要用到,比如游戏的 Buff 实现,Redis 中的过期任务,Linux 中的定时任务&a…

java——多线程

文章目录 Java 的并发基础知识1. 创建线程2. 同步方法和同步代码块3. 线程安全的容器4. volatile 关键字5. Lock 和 Condition 接口 Java 多线程编程的基本框架1. 创建和启动线程2. 线程的状态转换3. 线程安全4. 死锁 Java 并发编程的高级技术1. 线程池2. 并发集合3. 原子类4. …

测试:进阶篇

在本篇章开始之前,先对之前的内容进行一个简单的总结回顾一下: 基于需求设计测试用例,这里有个测试用例的万能公式: 功能(如果是软件,需要参考依据需求规格说明书;如果是物体,这个…

2023年7月电脑选择

文章目录 一、笔记本1.1 确定需求1.2 确定预算1.3 性能指标1.4 其他 二、台式电脑 最近有朋友让我推荐一下能做3D建模的笔记本电脑,本文就讲一下台式机和笔记本怎么选择。 一、笔记本 1.1 确定需求 当我们在选择笔记本时,首先需要确定自己的需求&#x…

CSS基础学习--24 表单

一、一个表单案例&#xff0c;我们使用 CSS 来渲染 HTML 的表单元素 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>CSS基础学习-表单</title> </head> <style> input[typetext], select {width:…

计算机基础--->数据结构(3)【堆(超详细)】

文章目录 堆堆的时间复杂度堆的分类堆的存储堆的操作插入元素删除堆顶元素 堆排序建堆排序 所有操作代码 堆 堆一般分为两种类型&#xff1a;最大堆和最小堆。在最大堆中&#xff0c;父节点的值总是大于或等于子节点的值&#xff0c;而在最小堆中&#xff0c;父节点的值总是小于…

计算机自我介绍500字范文(合集)

计算机自我介绍500字范文1 本人是___大学计算机系统维护专业的学生。大学四年的学习&#xff0c;积累了丰富的专业知识&#xff0c;广泛的人际关系&#xff0c;培养我成为一个敢于承担责任&#xff0c;对待生活乐观积极&#xff0c;吃苦耐劳的青年。在专业方面我的主攻方向是计…

Ffmpeg6.0版本源码解读第一期!

前言&#xff1a; 大家好&#xff0c;最近一直在直播讲解Ffmpeg6.0版本的源码解析&#xff0c;这里要明白学习源码能给我们带来什么好处&#xff1f;我相信很多小伙伴已经用过Ffmpeg去开发&#xff0c;不知道大家有没有在开发的过程&#xff0c;调用接口的时候&#xff0c;是否…

PowerDesigner面向对象建模-常用UML图

1 PowerDesigner简介 PowerDesigner最初由Xiao-Yun Wang&#xff08;王晓昀&#xff09;在SDP Technologies公司开发完成。PowerDesigner是Sybase的企业建模和设计解决方案&#xff0c;采用模型驱动方法&#xff0c;将业务与IT结合起来&#xff0c;可帮助部署有效的企业体系架…

python熟悉python基础语法,了解html网络结构,了解json格式数据,含有字符串

前言 Python网络爬虫是利用Python编写的程序&#xff0c;通过自动化地访问网页、解析html或json数据&#xff0c;并提取所需信息的技术。下面将详细介绍一些与Python网络爬虫相关的重要知识点。 1、Python基础语法&#xff1a; 变量和数据类型&#xff1a;学习如何声明变量以及…

使用R语言绘制富集条形图,轻松分析基因表达数据

一、引言 富集分析&#xff08;enrichment analysis&#xff09;是一种生物信息学方法&#xff0c;它可以帮助我们识别基因或其他的生物实体在某个特定的类别中过度表示的趋势。通俗来说&#xff0c;富集分析通过将基因分类到特定的集合中&#xff0c;然后根据基因在集合中的分…

万字长文带你深入理解JavaNIO并手动实现多人聊天室

NIO 网络编程 代码已同步至GitCode&#xff1a;https://gitcode.net/ruozhuliufeng/java-project.git Java NIO简介 IO概述 ​ IO的操作方式通常分为几种&#xff1a;同步阻塞BIO、同步非阻塞NIO、异步非阻塞AIO。 ​ &#xff08;1&#xff09;在JDK1.4之前&#xff0c;我们…

哈希表/散列表(HashTable)c++实现

目录 哈希表实现的思想 除留余数法 哈希冲突 第一种方法&#xff1a;探测法实现哈希表 探测法的思想 结点类 插入数据(insert) 冲突因子 数据扩容 哈希值 插入的代码实现以及哈希类 查找数据(find) 删除数据(erase) 第二种方法&#xff1a;拉链法实现哈希表 …

Kotlin~迭代器模式

概念 提供一种遍历集合元素的方法&#xff0c;而不暴露集合内部的实现。 角色介绍 iterator 迭代器接口: 定义访问和遍历集合元素的接口&#xff0c;一般包含next和hasNext方法。concrete iterator 具体迭代器: 实现迭代器接口&#xff0c;迭代器的核心逻辑实现。aggregate …

极致呈现系列之:Echarts热力图的神奇光晕

目录 什么是热力图热力图的特性及应用场景热力图的特性热力图的应用场景 Echarts中热力图的常用属性vue3中创建热力图 什么是热力图 热力图&#xff08;Heatmap&#xff09;是一种基于颜色映射的数据可视化图表&#xff0c;用于展示数据点的密度和分布情况。它使用不同的颜色强…

RT-Thread-10-线程优先级翻转

线程优先级翻转 前面讲到信号量和互斥量&#xff0c;二者有些区别&#xff1a; 信号量&#xff0c;可以在任何线程&#xff08;以及中断&#xff09;释放&#xff0c;用于同步&#xff0c;线程只在获得许可时才可以运行&#xff0c;强调的是运行步骤&#xff1b; 互斥量&#…