数据库的4种隔离级别

2023-11-13

数据库事务的隔离级别有4种,由低到高分别为Read uncommitted 、Read committed 、Repeatable read 、Serializable 。而且,在事务的并发操作中可能会出现脏读,不可重复读,幻读。下面通过事例一一阐述它们的概念与联系。

  脏读、不可重复读、幻象读概念说明:  

  脏读:指当一个事务正在访问数据,并且对数据进行了修改,而这种数据还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据还没有提交那么另外一个事务读取到的这个数据我们称之为脏数据。依据脏数据所做的操作肯能是不正确的。
  不可重复读:指在一个事务内,多次读同一数据。在这个事务还没有执行结束,另外一个事务也访问该同一数据,那么在第一个事务中的两次读取数据之间,由于第二个事务的修改第一个事务两次读到的数据可能是不一样的,这样就发生了在一个事物内两次连续读到的数据是不一样的,这种情况被称为是不可重复读。
  幻象读:一个事务先后读取一个范围的记录,但两次读取的纪录数不同,我们称之为幻象读(两次执行同一条 select 语句会出现不同的结果,第二次读会增加一数据行,并没有说这两次执行是在同一个事务中)


 读未提交 (Read uncommitted)

  读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。

  事例:老板要给程序员发工资,程序员的工资是3.6万/月。但是发工资时老板不小心按错了数字,按成3.9万/月,该钱已经打到程序员的户口,但是事务还没有提交,就在这时,程序员去查看自己这个月的工资,发现比往常多了3千元,以为涨工资了非常高兴。但是老板及时发现了不对,马上回滚差点就提交了的事务,将数字改成3.6万再提交。

  分析:实际程序员这个月的工资还是3.6万,但是程序员看到的是3.9万。他看到的是老板还没提交事务时的数据。这就是脏读。因此,在这种隔离级别下,查询是不会加锁的,也由于查询的不加锁,所以这种隔离级别的一致性是最差的,可能会产生“脏读”、“不可重复读”、“幻读”。如无特殊情况,基本是不会使用这种隔离级别的。

  那怎么解决脏读呢?Read committed!读提交,能解决脏读问题。


 读提交(Read Committed)

  读提交,顾名思义,就是只能读到已经提交了的内容

  事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(程序员事务开启),收费系统事先检测到他的卡里有3.6万,就在这个时候!!程序员的妻子要把钱全部转出充当家用,并提交。当收费系统准备扣款时,再检测卡里的金额,发现已经没钱了(第二次检测金额当然要等待妻子转出金额事务提交完)。程序员就会很郁闷,明明卡里是有钱的…

  分析:这就是读提交,若有事务对数据进行更新(UPDATE)操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,可以解决脏读问题。但在这个事例中,出现了一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读。

   这是各种系统中最常用的一种隔离级别,也是SQL Server和Oracle的默认隔离级别。这种隔离级别能够有效的避免脏读,但除非在查询中显示的加锁,如:

select * from T where ID=2 lock in share mode;
select * from T where ID=2 for update;

  不然,普通的查询是不会加锁的。

  那为什么“读提交”同“读未提交”一样,都没有查询加锁,但是却能够避免脏读呢?

  这就要说道另一个机制“快照(snapshot)”,而这种既能保证一致性又不加锁的读也被称为“快照读(Snapshot Read)”

  假设没有“快照读”,那么当一个更新的事务没有提交时,另一个对更新数据进行查询的事务会因为无法查询而被阻塞(因为上了X锁,即写锁,所以不能得到S锁,即读锁),这种情况下,并发能力就相当的差。而“快照读”就可以完成高并发的查询,不过,“读提交”只能避免“脏读”,并不能避免“不可重复读”和“幻读”。

  那怎么解决可能的不可重复读问题?Repeatable read !


可重复读(Repeated Read)

  可重复读,顾名思义,就是专门针对“不可重复读”这种情况而制定的隔离级别,自然,它就可以有效的避免“不可重复读”。而它也是MySql的默认隔离级别。

  事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(事务开启,不允许其他事务的UPDATE修改操作),收费系统事先检测到他的卡里有3.6万。这个时候他的妻子不能转出金额了。接下来收费系统就可以扣款了。

  分析:重复读可以解决不可重复读问题。写到这里,应该明白的一点就是,不可重复读对应的是修改,即UPDATE操作。但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作。

什么时候会出现幻读?

  事例:程序员某一天去消费,花了2千元,然后他的妻子去查看他今天的消费记录(全表扫描FTS,妻子事务开启),看到确实是花了2千元,就在这个时候,程序员花了1万买了一部电脑,即新增INSERT了一条消费记录,并提交。当妻子打印程序员的消费记录清单时(妻子事务提交),发现花了1.2万元,似乎出现了幻觉,这就是幻读。

  在这个级别下,普通的查询同样是使用的“快照读”,但是,和“读提交”不同的是,当事务启动时,就不允许进行“修改操作(Update)”了,而“不可重复读”恰恰是因为两次读取之间进行了数据的修改,因此,“可重复读”能够有效的避免“不可重复读”,但却避免不了“幻读”,因为幻读是由于“插入或者删除操作(Insert or Delete)”而产生的。

  那怎么解决幻读问题?Serializable!


序列化 Serializable

  这是数据库最高的隔离级别,这种级别下,事务“串行化顺序执行”,也就是一个一个排队执行。这种级别下,“脏读”、“不可重复读”、“幻读”都可以被避免,但是执行效率奇差,性能开销也最大,所以基本没人会用。


值得一提的是:大多数数据库默认的事务隔离级别是Read committed,比如Sql Server , Oracle。Mysql的默认隔离级别是Repeatable read。

 MySql如何解决幻读问题?

(1)什么是幻读

  • 前提条件:InnoDB引擎,可重复读隔离级别,使用当前读时。

    在一次事务里面,多次查询之后,结果集的个数不一致的情况叫做幻读。而多出来或者少的哪一行被叫做 幻行

  • 表现:一个事务(同一个read view)在前后两次查询同一范围的时候,后一次查询看到了前一次查询没有看到的行。两点需要说明:
      1、在可重复读隔离级别下,普通查询是快照读,是不会看到别的事务插入的数据的,幻读只在当前读下才会出现。
      2、幻读专指新插入的行,读到原本存在行的更新结果不算。因为当前读的作用就是能读到所有已经提交记录的最新值。

(2)幻读产生的原因

  行锁只能锁住行,即使把所有的行记录都上锁,也阻止不了新插入的记录。 

(3)如何解决幻读?

  • 在快照读读情况下,mysql通过mvcc来避免幻读。
  • 在当前读读情况下,mysql通过next-key来避免幻读

备注:什么是快照读、当前读

- 快照读, 读取专门的快照 (对于RC,快照(ReadView)会在每个语句中创建。对于RR,快照是在事务启动时创建的)
```
简单的select操作即可(不需要加锁,如: select ... lock in share mode, select ... for update)
```
针对的也是select操作

- 当前读, 读取最新版本的记录, 没有快照。 在InnoDB中,当前读取根本不会创建任何快照。
```
select ... lock in share mode

select ... for update

insert

update

delete

针对如下操作, 会让如下操作阻塞:    
```
insert
update
delete
```
- 在RR(可重复读)级别下, 快照读是通过MVVC(多版本控制)和undo log来实现的,

当前读是通过手动加record lock(记录锁)和gap lock(间隙锁)来实现的。所以从上面的显示来看,如果需要实时显示数据,还是需要通过加锁来实现。这个时候会使用next-key技术来实现。所以说

 总结一下:

  • 为什么会出现“脏读”?因为没有“select”操作没有规矩。
  • 为什么会出现“不可重复读”?因为“update”操作没有规矩。
  • 为什么会出现“幻读”?因为“insert”和“delete”操作没有规矩。
  • “读未提(Read Uncommitted)”能预防啥?啥都预防不了。
  • “读提交(Read Committed)”能预防啥?使用“快照读(Snapshot Read)”,避免“脏读”,但是可能出现“不可重复读”和“幻读”。
  • “可重复读(Repeated Red)”能预防啥?使用“快照读(Snapshot Read)”,锁住被读取记录,避免出现“脏读”、“不可重复读”,但是可能出现“幻读”。
  • “串行化(Serializable)”能预防啥?排排坐,吃果果,有效避免“脏读”、“不可重复读”、“幻读”,不过效果谁用谁知道。

出处:https://blog.csdn.net/qq_33290787/article/details/51924963

  https://baijiahao.baidu.com/s?id=1611918898724887602&wfr=spider&for=pc

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据库的4种隔离级别 的相关文章

  • python 没有名为serial的模块

    我的 python 程序有问题 我编写了程序来将数据 温度 从 arduino 获取到我的树莓派 sqlite 数据库 但它在第 4 行 导入串行 处给了我一个错误 提示 ImportError 没有名为串行的模块 我使用 python3
  • 删除 mysql 数据库中超过 3 个月的行的作业

    我们使用 mysql 服务器作为集中式日志系统 我希望有一项工作来定期删除 清理超过 3 个月的表条目 做这个的最好方式是什么 提前致谢 hinling 您是否在字段中存储项目的创建日期 If so DELETE FROM myTable
  • 拉拉维尔; “SQLSTATE[HY000] [2002] 连接被拒绝”

    我在 OSX 主机上设置了 homestead 2 0 并使用 Sequel Pro 我可以进行迁移并确认数据已在Sequel Pro中迁移 因此看起来数据库连接没有问题 但是 一旦我尝试从 Laravel 4 2 应用程序获取数据 它就无
  • 如何将彼此“接近”的纬度/经度点分组?

    我有一个用户提交的纬度 经度点的数据库 并且正在尝试将 接近 点分组在一起 接近 是相对的 但目前看来约为 500 英尺 起初 我似乎只能按前 3 个小数位具有相同纬度 经度的行进行分组 大约是一个 300x300 的盒子 了解当您远离赤道
  • VBScript:从 Scripting.Dictionary 中对项目进行排序

    我有下面的代码 它获取这样的数据 姓名 1 姓名 4 姓名 2 姓名 3 并像这样列出 是一个复选框 姓名 1 姓名 4 姓名 2 姓名 3
  • Riak 在 MapReduce 查询中失败。使用哪种配置?

    我正在与 riak riak js 结合开发一个 nodejs 应用程序 并遇到以下问题 运行此请求 db mapreduce add logs run 正确返回存储在存储桶日志中的所有 155 000 个项目及其 ID logs 1GXt
  • 通过 SQLAlchemy 获取随机行

    如何使用 SQLAlchemy 从表中选择一个或多个随机行 这在很大程度上是一个特定于数据库的问题 我知道 PostgreSQL SQLite MySQL 和 Oracle 具有通过随机函数排序的能力 因此您可以在 SQLAlchemy 中
  • SQLite (Android):使用 ORDER BY 更新查询

    Android SQLite 我想要在 myTable 中的其他行之间插入行在android中使用SQLite 为此 我尝试增加从第 3 行开始的所有行的 id 这样 我就可以在位置 3 处插入新行 myTable 的主键是列 id 表中没
  • 如何更新 pl/sql 中嵌套表的列? [复制]

    这个问题在这里已经有答案了 我正在尝试在表中创建一个可以存储多个值的列 如下所示 我有一个学生id std和一个名为marks可以采用几个值 例如2 3 4 我想更新此列表以添加另一个标记2 3 4 5但我不知道怎么做 我如何更新专栏mar
  • 一个表可以有多个主键吗?

    我现在很困惑 也许你可以帮助我更好地理解这个问题 即一个表可以有两个主键 如果是 那么如何 如果没有 那为什么 您询问是否可以有多个主键field你当然可以 您只能有一个主键 但它可以包含唯一标识行所需的任意数量的列 创建表时使用类似这样的
  • 数据聚合和缓存:如何按时间间隔快速绘制大型时间序列数据集的图表

    我有一个巨大的时间序列数据集 我想绘制图表 时间序列可以追溯到 5 年前 从后端的角度来看 以各种分辨率 间隔 显示这些数据的常用方法是什么 本质上我想绘制这样的数据图表 https bitcoinwisdom com markets bi
  • 可以重复应用并产生相同结果的数据库操作吗?

    我现在一片空白 或者像有些人说的那样 正在经历一个高级时刻 我知道这个概念有一个正式的定义和名称 其中在数据库中运行的数据库操作 存储过程 如果重复运行将产生相同的结果 它属于数学家的自反 对称 传递等类型 您的意思是 确定性 吗 如果使用
  • AWS RDS MySql - 如何在设置“公开可用”后允许访问

    刚刚使用默认设置和用户 密码创建了新的 AWS RDS MySql 实例 我也将其设置为publicly available并在此过程中创建新的 VPC 目前无法从我的笔记本电脑连接到此 RDS mysql h endpoint u myu
  • mysql表中的数据非常大。即使 select 语句也需要很多时间

    我正在开发一个数据库 它是一个相当大的数据库 有 13 亿行和大约 35 列 这是我检查表状态后得到的结果 Name Table Name Engine InnoDB Version 10 Row format Compact Rows 1
  • postgresql 不同的不工作

    我使用以下代码从数据库获取值 但是当我编写这段代码时 测试看看问题出在哪里 我注意到查询没有从数据库中获取不同的值 这是查询 select distinct ca id as id acc name as accName pIsu name
  • 如何使用Java获取特定模式的所有表及其列?

    我有一个数据库架构 其名称为 Navid 这个模式中有很多表 当然每个表都有一些列 我需要的是一个java类 连接到我的数据库 有一个在所有表上循环的方法 2 1 有一个内部循环来定义表的所有列 制作创建表查询语句 我想在另一个数据库中创建
  • 将数据库与 Clojure 结合使用

    有哪些使用 Clojure 数据库的方法 我从 Clojure 知道你可以用 Java 做任何事情 但这意味着我最终可能会使用一些过于复杂的东西 比如 Hibernate 这与 Clojure 的简单性相冲突 有什么建议或意见吗 Cloju
  • 如何修复 pgbackups 错误:备份 url 无效?

    我正在尝试按照迁移到 Cedar 的说明进行操作 除了我进行了重大重写 因此这不是前一个应用程序的分支 而是一个单独的分支 并停留在数据库迁移步骤 我安装了 pgbackup 和 heroku postgresql 插件 但得到了这个结果
  • 如何使用 Wix 运行 sql 脚本创建数据库

    我在使用 Wix 创建数据库时遇到问题 我能找到的示例 参见下面的链接 都是首先使用 wix 创建数据库并运行创建表 sql 脚本 问题是我需要将 wix 设置为使用 CREATE DATABASE 运行 sql 脚本来创建数据库和表 而不
  • 如何对 SQL 进行多次查询

    我正在尝试创建一个表 并在 PHP 脚本的帮助下在数据库中插入一些值 虽然只插入 1 行 但效果很好 当我尝试输入更多行数时 出现错误 我需要为每个查询编写完整的插入语句 因为我正在使用在线 Excel 到 SQL 查询转换器

随机推荐

  • 帧、报文、报文段、分组、包、数据报的概念区别

    1 报文 message 我们将位于应用层的信息分组称为报文 报文是网络中交换与传输的数据单元 也是网络传输的单元 报文包含了将要发送的完整的数据信息 其长短不需一致 报文在传输过程中会不断地封装成分组 包 帧来传输 封装的方式就是添加一些
  • 【ARM】Linux内核驱动之中断

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https gitee com stylle linux code 点赞 收藏 再看 养成习惯 订阅的粉丝可通过PC端文末加我微信 可对文章的内容进
  • Microsoft.Web.WebView2 初体验

    上篇已经介绍了WebView2的背景 今天有时间尝试一下 文档地址 https docs microsoft com zh cn dotnet api microsoft web webview2 winforms webview2 exe
  • Django基于用户画像的电影推荐系统源码(项目源代码)

    一 项目介绍 公众号 yk 坤帝 获取全部源代码 本系统是以Django作为基础框架 采用MTV模式 数据库使用MongoDB MySQL和Redis 以从豆瓣平台爬取的电影数据作为基础数据源 主要基于用户的基本信息和使用操作记录等行为信息
  • 微信分享引导页效果

    span style font size 18px span
  • java的rmi

    写在前面 本文看下如何通过Java原生提供的rmi功能来调用远端JVM对象的方法 并获取其结果 1 定义远端service pojo 使用了lombok Getter Setter ToString public class User im
  • 在较新版pycharm中使用conda虚拟环境的两种方法-保姆级教程

    文章目录 方法一 配置解释器 方法二 命令行直接调用 注意事项 方法一 配置解释器 首先创建new project 之后等待配置索引等文件即可 方法二 命令行直接调用 在终端terminal中直接使用conda activate xxx 但
  • 计算机网络工程毕业设计题目选题大全

    文章目录 0 简介 1 如何选题 2 最新网络工程选题 2 1 Java web SSM 系统 2 2 大数据方向 2 3 人工智能方向 2 4 其他方向 4 最后 0 简介 学长搜集分享最新的网络工程专业毕设毕设选题 难度适中 适合作为毕
  • js复制一个对象的方法,不改变原对象

    复制一个对象 不改变原对象简单方法如下 var obj a 1 b 2 es6新方法 Object assign var newObj Object assign obj es6新方法 扩展运算符 var newObj obj 有个弊端 就
  • 什么是网络编程?

    目录 一 UDP DatagramSocket DatagramPacket 服务器 客户端 二 TCP ServerSocket Socke 服务器 客户端 网络编程指的就是网络上的主机通过不同的进程 以编程的方式实现网络信息传输 而提到
  • CSDN如何调节成黑色主题,手把手教学

    今天师弟来问我 有没有把浏览器调节成黑色主题的东东 每天看网页很久 白色太刺眼了 作为未来的新晋程序员 也显得不专业 想到自己有个插件 就分享了出来 获得好评 有需求的地方就有分享 首先上效果图 随便打开一篇文章看一看 教程 首先 要用谷歌
  • 5G技术详解系列-PDU会话签约数据(6)

    相关文章会在公众号同步更新 公众号 5G通信大家学 持续更新的相关5G内容都是直接根据3GPP整理 保证更新内容的准确性 避免通过二手 甚至多手的资料 以讹传讹误导网友 在介绍完流程详解后 会整理专题内容 比如切片 服务发现 QoS流端到端
  • 我的世界java版怎么加整合包_我的世界Minecraft Mod(模组)安装指南

    前言 Mod的安装方法主要分为核心Jar文件手动覆盖安装和使用Forge加载 现在大多数的Mod基本都是依赖于Forge来加载Mod 不过对于刚接触我的世界的玩家来说 在安装Mod的时候也是一头雾水 导致安装Mod后 出现诸如游戏崩溃 黑屏
  • 【从零开始的Java开发】1-6-2 泛型:概述、泛型作为方法参数、自定义泛型、自定义泛型方法

    文章目录 泛型概述 泛型作为方法参数 自定义泛型 一个参数 两个参数 自定义泛型方法 总结 泛型概述 为什么要有泛型 在Java增加泛型之前 泛型程序设计使用继承来实现 坏处 需要强制转换 可向集合中添加任意类型的对象 存在风险 泛型的使用
  • 主干光缆线路的组网结构

    主干光缆是指连接主干光交与业务汇聚节点 以及主干光交之间的光缆 业务汇聚点指安装了OLT设备的节点 主干光交内的业务端口与业务汇聚点ODF间的光纤链路部分或全部是直连的 中间没有活动连接 主干光缆线路的组网结构一般分为 环形 树形和星形 1
  • 嵌入式Linux设备读取CPU温度的方法

    1 ARM 平台下 cat sys devices virtual thermal thermal zone0 temp62374 cat sys class thermal thermal zone0 temp 64036x86 平台下
  • vue项目配置rem移动端适配

    一 项目介绍 脚手架CLI vue cli Vue版本 2 6 11 移动UI组件库 Vant 2 10 14 CSS预处理器 sass 二 配置lib flexible插件 下载插件 npm i D lib flexible 导入 在sr
  • 据说,80%的人都搞不懂哈希算法 区块链 哈希算法

    本文约9000字 阅读 观看 需要52分钟 聊到区块链的时候也少不了会听到 哈希 哈希函数 哈希算法 是不是听得一头雾水 别急 这一讲我们来讲讲什么是哈希算法 哈希是一种加密算法 哈希函数 Hash Function 也称为散列函数或杂凑函
  • 车辆贷款违约预测

    1 案例介绍 国内某贷款机构的车贷业务面临借款人拖欠还款或拒不还款 导致该机构的不良贷款率居高不下的问题 该机构将部分贷款数据开放 诚邀大家帮助他们建立风险识别模型来预测可能违约的借款人 敏感信息已脱敏 给定某机构实际业务中的相关借款人信息
  • 数据库的4种隔离级别

    数据库事务的隔离级别有4种 由低到高分别为Read uncommitted Read committed Repeatable read Serializable 而且 在事务的并发操作中可能会出现脏读 不可重复读 幻读 下面通过事例一一阐