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…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...