MySQL中的事务隔离全详解
第一部分:MySQL事务的特性与并行事务引发的问题
1. 什么是事务及其四大特性(ACID)?
事务(Transaction)是数据库操作的基本单位,它将一组操作组合在一起,以确保这些操作作为一个整体被执行。如果事务中的某个操作失败,所有的更改都会回滚(撤销),保证数据的完整性和一致性。
事务的四大特性,通常用 ACID(Atomicity, Consistency, Isolation, Durability)来表示:
-
原子性(Atomicity)
- 定义:事务是一个不可分割的整体,要么全部执行,要么全部不执行。
- 举例:银行转账时,假设从账户 A 转账 100 元到账户 B,包括两个操作:
- 从 A 减少 100 元。
- 向 B 增加 100 元。
如果任意一个操作失败,整个事务都必须回滚,确保账户余额不会出现错误。
-
一致性(Consistency)
- 定义:事务执行前后,数据库都必须保持一致的状态。这意味着,所有事务必须从一个有效的数据库状态转到另一个有效的状态。
- 举例:假设 A 和 B 的账户总余额为 1000 元,无论转账操作发生何种中断,事务的完成后,总余额必须仍然是 1000 元。
-
隔离性(Isolation)
- 定义:多个事务并发执行时,一个事务的执行不能受到其他事务的干扰。每个事务就像独立运行在数据库中一样,其执行过程对其他事务是不可见的。
- 举例:如果 A 向 B 转账时,另一个事务查询账户 B 的余额,必须等到转账事务完成后才能看到更新后的数据,否则查询的结果可能不准确。
-
持久性(Durability)
- 定义:事务一旦提交,其所做的更改就会永久存储在数据库中,即使系统发生故障也不会丢失。
- 举例:如果银行系统发生断电,但 A 转账给 B 的操作已经提交,那么重启后,转账操作仍然有效,数据不会丢失。
2. 并行事务可能引发的问题
在并发环境中,多个事务同时操作数据库,可能导致以下问题:
-
脏读(Dirty Read)
- 定义:一个事务读取了另一个事务未提交的数据。
- 场景:
- 事务 A 修改了账户 B 的余额,将其从 500 元改为 300 元,但尚未提交。
- 事务 B 读取了账户 B 的余额为 300 元。
- 如果事务 A 回滚,账户 B 的余额又恢复到 500 元,此时事务 B 的读取结果就不正确了。
-
不可重复读(Non-Repeatable Read)
- 定义:一个事务在两次读取同一数据时,发现数据不一致,数据被其他事务修改了。
- 场景:
- 事务 A 查询账户 B 的余额,第一次读到 500 元。
- 事务 B 修改账户 B 的余额为 300 元并提交。
- 事务 A 再次读取账户 B 的余额,发现变成了 300 元,数据与第一次读取不一致。
-
幻读(Phantom Read)
- 定义:一个事务在读取某个范围的数据时,发现范围内的数据被其他事务插入或删除了,导致前后查询结果不一致。
- 场景:
- 事务 A 查询工资大于 5000 的员工数,第一次查到 5 个员工。
- 事务 B 插入了一名工资为 6000 的新员工并提交。
- 事务 A 再次查询,发现工资大于 5000 的员工变成了 6 个,出现了“幻影”记录。
第二部分:MySQL的事务隔离级别及其实现
为了解决并发事务引发的问题,SQL 标准定义了 四种事务隔离级别,MySQL 也提供了相应的支持。隔离级别由低到高分别是:
- 读未提交(Read Uncommitted)
- 读已提交(Read Committed)
- 可重复读(Repeatable Read)
- 可序列化(Serializable)
1. 什么是事务隔离级别?
事务隔离级别决定了一个事务能看到其他事务所做更改的程度。隔离级别越高,事务之间的干扰越少,但性能可能受到影响。
MySQL 默认使用的存储引擎 InnoDB 实现了所有隔离级别,通过锁机制和多版本并发控制(MVCC)来实现隔离。
2. 四种隔离级别的详细介绍
1. 读未提交(Read Uncommitted)
- 定义:一个事务可以读取其他事务尚未提交的更改。
- 问题:
- 存在脏读问题。
- 不可重复读和幻读问题仍然存在。
- 场景:
- 事务 A 修改某记录,将余额从 500 改为 300,但未提交。
- 事务 B 读取该记录时,余额显示为 300。
- 如果事务 A 回滚,事务 B 看到的数据就是错误的。
优缺点:
优点是并发性能高,缺点是数据不可靠。适用于对事务一致性要求极低的场景。
2. 读已提交(Read Committed)
- 定义:一个事务只能读取到其他事务已提交的数据。
- 问题:
- 解决了脏读问题。
- 不可重复读和幻读问题仍然存在。
- 场景:
- 事务 A 修改记录,将余额从 500 改为 300,但未提交,事务 B 无法看到此更改。
- 事务 A 提交后,事务 B 再读取该记录,看到余额为 300。
优缺点:
数据一致性较高,适用于大多数应用场景。Oracle 数据库默认使用此级别。
3. 可重复读(Repeatable Read)
- 定义:在一个事务中多次读取相同数据时,结果始终一致,即使其他事务修改了数据。
- 问题:
- 解决了脏读和不可重复读问题。
- 但幻读问题仍然存在。
- 场景:
- 事务 A 查询某记录,第一次读取余额为 500。
- 事务 B 修改该记录的余额为 300 并提交。
- 在事务 A 中再次读取余额,结果仍为 500,保持一致。
优缺点:
通过 MVCC 技术解决不可重复读问题,InnoDB 默认使用此级别。
4. 可序列化(Serializable)
- 定义:通过强制事务按顺序执行,确保完全隔离。
- 问题:
- 解决了脏读、不可重复读和幻读问题。
- 并发性能最低。
- 场景:
- 事务 A 查询工资大于 5000 的员工数。
- 事务 B 插入一名工资为 6000 的新员工,必须等待事务 A 提交后才能执行。
优缺点:
完全隔离,数据一致性最强,但性能开销大,适合高要求的金融场景。
3. 隔离级别对并发问题的解决情况
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(RU) | √ | √ | √ |
读已提交(RC) | × | √ | √ |
可重复读(RR) | × | × | √ |
可序列化(S) | × | × | × |
4. MySQL 隔离级别的实现细节
MySQL 的 InnoDB 存储引擎通过以下机制实现隔离级别:
-
锁机制
- 行级锁:对单行记录进行加锁,减少锁冲突,提高并发性能。
- 间隙锁(Gap Lock):锁定索引范围,避免幻读问题。
-
MVCC(多版本并发控制)
- 在可重复读隔离级别下,使用 MVCC 技术为每个事务提供“时间点快照”,避免读取到其他事务的修改。
第三部分:事务隔离级别的性能影响、实际使用场景及实现方式
在选择事务隔离级别时,我们需要综合考虑数据一致性和系统性能,并了解每种隔离级别的具体实现原理。下面逐步展开分析:
1. 隔离级别的性能影响
事务隔离级别从低到高,对性能的影响逐渐增大:
-
读未提交(Read Uncommitted)
- 性能最高,因为不需要对数据加锁或者版本控制。
- 缺点是数据一致性最低,可能会读到未提交的临时数据,适合对数据准确性要求极低的场景(如临时报表统计)。
-
读已提交(Read Committed)
- 性能较高,仅使用短时间锁定,读取已提交数据,减少了脏读问题。
- 缺点是仍可能存在不可重复读和幻读问题,适用于 OLTP(在线事务处理)系统,例如大部分电商订单场景。
-
可重复读(Repeatable Read)
- 性能中等,通过 MVCC 技术避免不可重复读问题。
- 会引入间隙锁(Gap Lock)防止幻读,这可能导致更多锁争用,适合对数据一致性要求较高的业务场景,例如库存管理。
-
可序列化(Serializable)
- 性能最低,因为事务是串行执行的,需要加锁或控制访问范围,可能会导致大量事务等待。
- 适合高一致性需求的场景,例如金融转账、证券交易。
2. 实际使用场景建议
-
读未提交(RU)
适用于日志分析、临时数据汇总等场景,这些场景对数据的最终一致性要求不高。 -
读已提交(RC)
推荐作为通用隔离级别,适用于电商、社交平台等对性能和一致性均衡要求的场景。 -
可重复读(RR)
适用于需要保证多个查询结果一致的场景,例如库存查询或长时间事务操作。 -
可序列化(S)
使用场景较少,适用于需要严格一致性且并发量低的场景,如银行核心账户系统。
3. 四种隔离级别的实现方式
在 MySQL 中,隔离级别通过 锁机制 和 MVCC(多版本并发控制) 实现:
1. 读未提交(Read Uncommitted)的实现
- 实现机制:
- 不加锁,直接读取最新数据,即使这些数据未提交。
- 数据的可见性完全依赖于修改的事务状态,因此可能导致脏读。
2. 读已提交(Read Committed)的实现
- 实现机制:
- 读取数据时,事务只访问已经提交的版本。
- 使用短时锁(读锁)来保证读取的数据已经提交,避免脏读。
- MVCC 机制:为每个事务维护一个快照,读取时仅访问在事务启动时已经提交的数据版本。
3. 可重复读(Repeatable Read)的实现
- 实现机制:
- 使用 MVCC 技术,保证在一个事务内读取到的所有数据版本一致。
- 为了避免幻读问题,InnoDB 在范围查询时引入 间隙锁(Gap Lock),锁定数据范围,阻止其他事务插入新数据。
- 例子:
- 如果查询“工资 > 5000 的记录”,事务会锁住满足条件的记录以及索引范围,其他事务不能在范围内插入新记录。
4. 可序列化(Serializable)的实现
- 实现机制:
- 使用读写锁(Shared/Exclusive Lock)强制事务串行化。
- 事务读取数据时,会加共享锁(S 锁),其他事务无法修改;事务写入数据时,会加排他锁(X 锁),阻止其他事务读取或修改。
- 执行范围查询时,锁定整个查询范围,完全避免幻读。
相关文章:
MySQL中的事务隔离全详解
第一部分:MySQL事务的特性与并行事务引发的问题 1. 什么是事务及其四大特性(ACID)? 事务(Transaction)是数据库操作的基本单位,它将一组操作组合在一起,以确保这些操作作为一个整体…...

异常--C++
文章目录 一、异常的概念及使用1、异常的概念2、异常的抛出和捕获3、栈展开4、查找匹配的处理代码5、异常重新抛出6、异常安全问题7、异常规范 二、标准库的异常 一、异常的概念及使用 1、异常的概念 异常处理机制允许程序中独立开发的部分能够在运行时就出现的问题进行通信并…...

SeggisV1.0 遥感影像分割软件【源代码】讲解
在此基础上进行二次开发,开发自己的软件,例如:【1】无人机及个人私有影像识别【2】离线使用【3】变化监测模型集成【4】个人私有分割模型集成等等,不管是您用来个人学习还是公司研发需求,都相当合适,包您满…...
锁-读写锁-Swift
实现一 pthread_mutex_t: ReadWriteLock/Sources/ReadWriteLock at main SomeRandomiOSDev/ReadWriteLock GitHub https://swiftpackageindex.com/reers/reerkit/1.0.39/documentation/reerkit/readwritelock/ // // Copyright © 2022 reers. // // Pe…...

Kafka如何保证消息可靠?
大家好,我是锋哥。今天分享关于【Kafka如何保证消息可靠?】面试题。希望对大家有帮助; Kafka如何保证消息可靠? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Kafka通过多种机制来确保消息的可靠性,主要包…...

5.10【机器学习】
如果FLAG的画,就是已经有模型了,不然就新建一个模型,通过TORCH方法 在训练的时候,如果TRAIN的话就是训练,不然就是预测 forward前向预测出来一个结果,就是1234 在train方法里,进行多轮迭代&am…...

[白月黑羽]关于仿写股票数据软件题目的解答
原题: 对应问题视频: 实现的效果 不同点 实现的作品和原题要求的不同点 题目要求爬虫获取数据,作品中是调库获取所有股票历史数据实时数据使用爬虫的方式爬取指定股票的数据,需要实时更新,我做了修改,改…...

详解LZ4文件解压缩问题
详解LZ4文件解压缩问题 一、LZ4文件解压缩方法1. 使用LZ4命令行工具2. 使用Python库3. 使用第三方工具4. 在线解压工具 二、常见问题及解决方法1. 解压显示文件损坏2. 解压后文件大小异常 三、总结 LZ4是一种快速的压缩算法,广泛应用于需要实时压缩和解压缩大文件的…...
vue项目中单独文件的js不存在this.$store?.state怎么办
在Vue项目中,如果你在单独的文件(比如插件、工具函数等)中遇到this.$store不存在的情况,这通常是因为this上下文不指向Vue实例,或者Vuex store没有被正确地注入到Vue实例中。以下是几种可能的解决方案: 确保…...

Github提交Pull Request教程 Git基础扫盲(零基础易懂)
1 PR是什么? PR,全称Pull Request(拉取请求),是一种非常重要的协作机制,它是 Git 和 GitHub 等代码托管平台中常见的功能,被广泛用于参与社区贡献,从而促进项目的发展。 PR的整个过…...

Java函数式编程【二】【Stream的装饰】【中间操作】【map映射器】【摊平映射器flatMap】
一、Java的Stream流式编程中的中间操作 Java的Stream流式编程中,中间操作是对数据流进行处理的一种方式,这些操作通常返回流对象本身,以便可以链接更多的操作。以下是一些常见的中间操作: filter(Predicate predicate) - 用于通过…...
树莓派明明安装了opencv和numpy,却找不到
当然不止树莓派,配置python环境都可能存在这个问题 可能是因为安装的 numpy 或者 opencv 版本与 Python 的包路径不匹配。下面是问题的常见原因及解决方法:【方法一和二优先考虑】 原因分析 多版本 Python 环境冲突: 树莓派上可能有多个版本…...
numpy.float8不存在;Python中,实现16位浮点数
目录 python中矩阵的浮点数存储 numpy.float8不存在 Python中,实现16位浮点数 实现 float16 关于 float8 python中矩阵的浮点数存储 在Python中,矩阵通常是通过嵌套列表(list of lists)、NumPy数组(numpy.ndarray)或其他类似的数据结构来表示的。矩阵中存储的数值所…...

Redis集群配置 (不使用docker 部署)
1. Redis集群简介 1.1 什么是Redis集群 Redis集群是一种通过将多个Redis节点连接在一起以实现高可用性、数据分片和负载均衡的技术。它允许Redis在不同节点上同时提供服务,提高整体性能和可靠性。根据搭建的方式和集群的特性,Redis集群主要有三种模式&…...
HTML5系列(7)-- Web Storage 实战指南
前端技术探索系列:HTML5 Web Storage 实战指南 🗄️ 致读者:本地存储的新纪元 👋 前端开发者们, 今天我们将深入探讨 HTML5 中的 Web Storage 技术,这是一个强大的本地存储解决方案,让我们能…...

【在Linux世界中追寻伟大的One Piece】读者写者问题与读写锁
目录 1 -> 读者写者问题 1.1 -> 什么是读者写者问题 1.2 -> 读者写者与生产消费者的区别 1.3 -> 如何理解读者写者问题 2 -> 读写锁 2.1 -> 读写锁接口 3 -> 读者优先(Reader-Preference) 4 -> 写者优先(Writer-Preference) 1 -> 读者写者…...

用到动态库的程序运行过程
当我们写好了一段代码然后编译运行后会生成可执行文件,该文件会存在磁盘的当前目录下,而当我们开始运行这段程序时,操作系统(加载器)需要将其从磁盘加载进内存然后执行相关操作,而对于用到动态库的程序&…...

类型转换与IO流:C++世界的变形与交互之道
文章目录 前言🎄一、类型转换🎈1.1 隐式类型转换🎈1.2 显式类型转换🎁1. C 风格强制类型转换🎁2. C 类型转换操作符 🎈1.3 C 类型转换操作符详解🎁1. static_cast🎁2. dynamic_cast&…...
Pytorch使用手册- TorchVision目标检测微调Tutorial的使用指南(专题十二)
这篇教程的目标是对一个预训练的 Mask R-CNN 模型进行微调,应用于 Penn-Fudan 行人检测与分割数据集。该数据集包含 170 张图像,里面有 345 个行人实例,我们将通过这个教程来演示如何使用 torchvision 中的新特性,训练一个面向自定义数据集的目标检测和实例分割模型。 注意…...
人工智能机器学习算法分类全解析
目录 一、引言 二、机器学习算法分类概述 (一)基于学习方式的分类 1. 监督学习(Supervised Learning) 2. 无监督学习(Unsupervised Learning) 3. 强化学习(Reinforcement Learning…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...

以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...