sql怎么读_大白话讲解脏写、脏读、不可重复读和幻读

faac8c57a8e47013f41bf26785fedd09.png

一般对于我们的业务系统去访问数据库而言,它往往是多个线程并发执行多个事务的,对于数据库而言,它会有多个事务同时执行,可能这多个事务还会同时更新和查询同一条数据,所以这里会有一些问题需要数据库来解决

我们来看看,如果多个事务要是对缓存里的同一条数据同时进行更新或者查询,此时会产生哪些问题呢?这里实际上会涉及到脏写、脏读、不可重复读、幻读四种问题。

脏写

脏写,意思是说有两个事务,事务 A 和事务 B 同时在更新一条数据,事务 A 先把它更新为 A 值,事务 B 紧接着就把它更新为 B 值。如图:

cb831fbb037b23ad32ad2cb13f12f7d0.png

可以看到,此时事务 B 是后更新那行数据的值,所以此时那行数据的值是 B。而且此时事务 A 更新之后会记录一条 undo log 日志。因为事务 A 是先更新的,它在更新之前,这行数据的值为 NULL。所以此时事务 A 的 undo log 日志大概就是:更新之前这行数据的值为 NULL,主键为 XX

那么此时事务 B 更新完数据的值为 B,此时事务 A 突然回滚了,就会用它的 undo log 日志去回滚。此时事务 A 一回滚,直接就会把那行数据的值更新回 NULL 值。如图:

953acb75ab4d32f8ebbf0b6578eba4d2.png

然后就尴尬了,事务 B 一看,为什么我更新的 B 值没了?就因为你事务 A 反悔了把数据值回滚成 NULL 了,结果我更新的 B 值也不见 了。所以对于事务 B 看到的场景而言,就是自己明明更新了,结果值却没了,这就是脏写。

所谓脏写,就是我刚才明明写了一个数据值,结果过了一会却没了。而它的本质就是事务 B 去修改了事务 A 修改过的值,但是此时事务 A 还没提交,所以事务 A 随时会回滚,导致事务 B 修改的值也没了,这就是脏写的定义。

脏读

假设事务 A 更新了一行数据的值为 A 值,此时事务 B 去查询了一下这行数据的值,看到的值是 A 值,如图:

e2fa7398f16b185741ca08f8286654e4.png

接着,事务 B 拿着刚才查询到的 A 值做各种业务处理。但是接着坑爹的事情发生了,事务 A 突然回滚了事务,导致它刚才功能的 A 值没了,此时那行数据的值回滚为 NULL 值。然后事务 B 紧接着此时再次查询那行数据的值,看到的居然是 NULL 值。如图:

4cf044497fbec588f3e009b735695db3.png

这就是脏读。它的本质是事务 B 去查询了事务 A 修改过的数据,但是此时事务 A 还没提交,所以事务 A 随时会回滚导致事务 B 再次查询就读不到刚才事务 A 修改的数据了,这就是脏读。

其实总结一句话,无论是脏写还是脏读,都是因为一个事务去更新或者查询了另外一个还没提交的事务更新过的数据。因为另外一个事务还没提交,所以它随时可能会回滚,那么必然导致你更新的数据就没了,或者你之前查询到的数据就没了,这就是脏写和脏读两种场景。

不可重复读

假设我们有一个事务 A 开启了,在这个事务 A 里会多次对一条数据进行查询。然后呢,另外有两个事务,一个是事务 B,一个是事务 C,他们两都是对一条数据进行更新的。然后我们假设一个前提,就是比如说事务 B 更新之后,如果还没提交,那么事务 A 是读不到的,必须要事务 B 提交之后,它修改的值才能被事务 A 读取到,其实这种情况下,就是我们首先避免了脏读的发生

因为脏读的意思就是事务 A 可以读到事务 B 修改过还没提交的数据,此时事务 B 一旦回滚,事务 A 再次读就读不到了,那么此时就会发生脏读问题。我们现在假设的前提是事务 A 只能在事务 B 提交之后读取到它修改的数据,所以此时必然是不会发生脏读的

但是,此时会有另外一个问题,叫做不可重复读。假设缓存页里一条数据原来的值是 A 值,此时事务 A 开启之后,第一次查询这条数据,读取到的就是 A 值。如图:

e212d2955cbccb5fcae1208129ca57d6.png

接着事务 B 更新了那行数据的值为 B 值,同时事务 B 立马提交了,然后事务 A 此时还没提交。大家注意,此时事务 A 是没提交的,它在事务执行期间第二次查询数据,此时查到的是事务 B 修改过的值,B 值,因为事务 B 已经提交了,所以事务 A 是可以读到的,如图:

2f50e4594f6c1bbb6bebfc1ca50fe171.png

紧接着事务 C 再次更新数据为 C 值,并且提交事务了,此时事务 A 在还没提交的情况下,第三次查询数据,查到的值为 C 值,如下:

2b98621fb2b1e6b41b575f087d8d5a1d.png

那么上面的场景有什么问题呢?其实要说没问题也可以是没问题的,毕竟事务 B 和 事务 C 都提交之后,事务 A 多次查询查到它们修改的值,是 OK 的。但是你要说有问题,也可以是有问题的,就是事务 A 可能第一次查询到 A 值,那么它可能希望的是在事务执行期间,如果多次查询数据,都是同样的一个 A 值,它希望这个 A 值是它重复读取的时候一直可以读到的。它希望这行数据的值是可重复读的

但是此时,明显 A 值是不可重复读的。因为事务 B 和事务 C 一旦更新值并且提交了,事务 A 会读到别的值,所以此时这行数据的值是不可重复读的。此时对于你来说,这个不可重复读的场景,就是一种问题

上面描述的,其实就是不可重复读的问题,其实这个问题你说是问题也不一定就是什么大问题。因为这取决于你自己想要数据库是什么样子的,如果你希望看到的场景是不可重复读,也就是事务 A 在执行期间多次查询一条数据,每次都可以查到其它已经提交的事务修改过的值,那么就是不可重复读,如果你希望这样子,那也没问题。

如果你期望的是可重复读,但是数据库表现的是不可重复读,让你事务 A 执行期间多次查到的值都不一样,都的问题是别的提交过的事务修改过的,那么此时你就可以认为,数据库有问题,这个问题就是「不可重复读」

幻读

脏写、脏读和不可重复读都分别代表了不同的数据库问题。脏写就是两个事务没提交的状况下,都修改同一条数据,结果一个事务回滚了,把另外一个事务修改的值也撤销了,所谓脏写就是两个事务没提交状态下修改同一个值。

脏读就是一个事务修改了一条数据的值,结果还没提交呢,另外一个事务就读到了你修改的值,然后你回滚了,人家事务再次读,就读不到了,即人家事务读到了你修改之后还没提交的值,这就是脏读了。而不可重复读,针对的是已经提交的事务修改的值,被你事务给读到了,你事务内多次查询,多次读到的是别的已经提交的事务修改过的值,这就导致不可重复读。

接着我们说说幻读。简单来说,你一个事务 A,先发送一条 SQL 语句,里面有一个条件,要查询一批数据出来,如 SELECT * FROM table WHERE id > 10。然后呢,它一开始查询出来了 10 条数据。接着这个时候,别的事务 B往表里插了几条数据,而且事务 B 还提交了,此时多了几行数据。如图:

ed376d8318cfb85e8221e2e2c76a0d40.png

接着事务 A 此时第二次查询,再次按照之前的一模一样的条件执行 SELECT * FROM table WHERE id > 10 这条 SQL 语句,由于其他事务插入了几条数据,导致这次它查询出来了 12 条数据。如图:

d4ce847300af61ed45808b791d9dc3b9.png

于是事务 A 开始怀疑自己的眼镜了,为什么一模一样的 SQL 语句,第一次查询是 10 条数据,第二次查询是 12 条数据?难道刚才出现幻觉了?这就是「幻读」这个名词的由来

幻读就是你一个事务用一样的 SQL 多次查询,结果每次查询都会发现查到一些之前没看到过的数据。注意,幻读特指的是你查询到了之前查询没看到过的数据。此时说明你是幻读了

其实,脏写、脏读、不可重复读、幻读,都是因为业务系统会多线程并发执行,每个线程可能都会开启一个事务,每个事务都会执行增删改查操作。然后数据库会并发执行多个事务,多个事务可能会并发地对缓存页里的同一批数据进行增删改查操作,于是这个并发增删改查同一批数据的问题,可能就会导致我们说的脏写、脏读、不可重复读、幻读这些问题。

所以这些问题的本质,都是数据库的多事务并发问题,那么为了解决多事务并发问题,数据库才设计了事务隔离机制、MVCC 多版本隔离机制、锁机制,用一整套机制来解决多事务并发问题。

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

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

相关文章

Linux显示txt文件,如何在Linux中显示文本文件中的某些行?

sed -n 10000000,10000020p filename你可能能够加快这一点:sed -n 10000000,10000020p; 10000021q filename在这些命令中,选项-n使sed“抑制模式空间的自动打印”. p命令“print [s]当前模式空间”和q命令“立即退出[s] sed脚本而不再处理任何输入……”引号来自sed…

Android上试用Linphone(Free SIP VOIP Client)

1. 下载Linphone apk并且安装到两个Android手机上http://www.linphone.org/eng/download/packages/android.html2. 申请两个免费的SIP帐号进行测试https://www.ekiga.net/3. 在每个Android手机上分别配置Linphone应用程序点击Settings菜单, 在SIP Account界面分别配置如下:User…

greensock包使用

greensock包使用 官网: http://www.greensock.com/tweenlite/ 新的遮罩类:BlitMask类 http://www.snorkl.tv/2011/10/use-blitmasks-wrap-feature-for-easy-bitmap-scrolling-and-looping/ 转载于:https://www.cnblogs.com/tinytiny/archive/2013/01/10/…

esp8266 micropython oled_micropython(4):使用ESP8266 控制 oled 屏幕,并显示 helloworld 字符...

目录前言1,关于esp 8266 和 oled2,使用lib库驱动 1306 4pin led3,总结前言相关micropython 全部分类:https://blog.csdn.net/freewebsys/category_9670462.html本文的原文连接是:https://blog.csdn.net/freewebsys/article/detail…

linphone-android移植

一:到网站上下载linphone-android的源码: http://www.linphone.org/eng/download/git.html linphone-android对应的git地址是: 在虚拟机中敲入如下命令 git clone git://git.linphone.org/linphone-android.git --recursive 记住一定要把rescursive给带上&…

debian 升级linux内核,Debian8升级内核到4.5

本文讲述如何升级Debian8的内核到4.5版本0x01:去linux kernel官网https://www.kernel.org/下载4.5的内核,选择tar.xz格式0x02:想办法把下载好的包弄进你的虚拟机或...直接你的物理机0x03:解压有的朋友可能没见过tar.xz格式的包&am…

jQuery.validate.js API

名称 返回类型 描述 validate(options) 返回:Validator 验证所选的 FORM valid() …

一个小公司老板的日常管理

1. 小公司如何留住骨干: 2.关于授权 3.有的钱不能省 5.关于招聘 6.老板尽量唱红脸 7.公司里的亲戚 8.当老板和开车 9.按时发工资 10.学会说“不” 11.不要在公司内部奢望交朋友 12.避免当场做决定 13.政策的制定 14.矬子里拔将军 15.有些事情越透明越好 16.发劳保用…

软件安全测试报告模板_软件测试工程师经典面试题

软件测试工程师,和开发工程师相比起来,虽然前期可能不会太深,但是涉及的面还是比较广的。前期面试实习生或者一年左右的岗位,问的也主要是一些基础性的问题比较多。涉及的知识主要有MySQL数据库的使用、Linux操作系统的使用、软件…

linux怎么删除exe文件夹,ubuntu linux 批量删除文件

sudo sucd /find / -name "*google-music*" -exec rm -rf "{}" \; 注:分号是必需的find [目录名] -name "文件名" -exec rm -rf "{}" \;搜索删除文件,例如:find / -name *.raw -exec rm -rf &…

OD使用教程20 - 调试篇20

OD使用教程20 - 调试篇20 让编程改变世界 Change the world by program 名词注释:Keygen为Key Generator的缩写,就是我们一般所说的注册机。是软件注册生成所需的注册码或序列号的程序。 keygen可以独立做一个可执行程序存在,也可以作为程序…

堡垒机 请确认是否安装oracle客户端_OracleOracle数据库的安装(超详细)

一、Oracle的安装对于新手来说安装Oracle这样的数据库,第一次还是会有些陌生的,我自己在安装的过程中也是遇到的很多的坑。(自己装了5遍 /(ㄒoㄒ)/~~ )由于我自己安装的是11g这个版本,所以下面以11g的下载安装为例1.下载Oracle数据库是有免费…

linux编译器项目,编译器架构 LLVM

LLVM 是 Low Level Virtual Machine (低级虚拟机)的简称,这个库提供了与编译器相关的支持,可以作为多种语言编译器的后台来使用。能够进行程序语言的编译期优化、链接优化、在线编译优化、代码生成。LLVM的项目是一个模块化和可重复使用的编译器和工具技…

北漂周记--第2记--培训开始

写作地点:宿舍 本周日期:2012-3-5到2012-3-11 3月5日,上午看书,10点多时,开始安装VirtualBox,然后在虚拟机中挂在了XP系统,只可惜使用了 多种方法,也不能使用工商银行的U盾&#xff…

卡巴斯基安全浏览器_卡巴斯基杀毒软件被曝出用户上网痕迹泄露漏洞

近期,国外安全研究人员曝出卡巴斯基杀毒软件的脚本中存在一个独特而唯一的标识符,可导致用户在过去4年中访问过的每个网站都被泄露。该漏洞被标记为CVE-2019-8286,其中所涉及的独特标识可让被访问过的网站和第三方商业公司在线跟踪用户。更严…

windows安装linux无法启动服务,Windows系统下Apache服务器无法启动的问题解决

关于apache无法启动主要是80端口的问题,下面我们来看一下关于端口被占的处理办法解决方案:1:在dos下运行netstat -ano2:在xampp control panel中点setup打开命令界面,3:选择6 enable mob_perl4:重新启动xam…

栅格矢量化_学会用栅格系统,普通LOGO秒变高大上

经常看到很多 LOGO 初看一般,但只要加上了栅格线,感觉瞬间就上了一个档次。有个比较出名的例子,就是锤子手机的 LOGO。是不是觉得右边的栅格线加上之后,瞬间高大上了许多?那这些栅格线真的只能拿来展示吗?有…

js取消气泡事件、阻止浏览器的默认行为

1.阻止事件冒泡,使成为捕获型事件触发机制.取消tr里面子元素响应tr定义的事件,在tr子元素里面禁止气泡事件就可以&#xff0c;子元素事件中加入window.event.cancelBubbletrue 即可&#xff01; 例子&#xff1a;表格行有一个单击事件,例如:<table><tr οnclick"…

使用openssh-clients的scp命令来传输文件

系统环境&#xff1a;RedHat Enterprise Linux Server 6 主机desktop作为客户端&#xff0c;服务器为9.9.9.9(域名为www.huage.com) 以下4个实例均在客户端完成&#xff0c;此时并未通过ssh登录到www.huage.com 1、复制远程服务器的文件到本地&#xff1a; [rootdesktop huage]…

python alter table_python(pymysql)之mysql简单操作

一、mysql简单介绍说到数据库&#xff0c;我们大多想到的是关系型数据库&#xff0c;比如mysql、oracle、sqlserver等等&#xff0c;这些数据库软件在windows上安装都非常的方便&#xff0c;在Linux上如果要安装数据库&#xff0c;咱不得不首先推荐的是mysql数据库了&#xff0…