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

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

脏写

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

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

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

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

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

脏读

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

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

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

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

不可重复读

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

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

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

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

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

那么上面的场景有什么问题呢?其实要说没问题也可以是没问题的,毕竟事务 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 还提交了,此时多了几行数据。如图:

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

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

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

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

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

大白话讲解脏写、脏读、不可重复读和幻读相关推荐

  1. mysql系列:加深对脏读、脏写、可重复读、幻读的理解

    关于相关术语的专业解释,请自行百度了解,本文皆本人自己结合参考书和自己的理解所做的阐述,如有不严谨之处,还请多多指教. **不可重复读的重点是修改: **同一事务,两次读取到的数据不一样. 幻读的重点 ...

  2. 脏读、重复读、幻读;

    脏读 所谓脏读是指一个事务中访问到了另外一个事务未提交的数据,如下图: 如果会话 2 更新 age 为 10,但是在 commit 之前,会话 1 希望得到 age,那么会获得的值就是更新前的值.或者 ...

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

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

  4. 大白话讲解脏写、脏读、可重复读和幻读

    文章目录 前言 1. 脏写 2. 脏读 3. 不可重复读 4. 幻读 前言 当多个事务并发执行的时候,会导致什么问题? 我们知道,执行sql是在buffer pool中对数据进行查询或者修改.如若多个 ...

  5. 不可重复读和幻读的区别_图解脏写、脏读、不可重复读、幻读

    MySQL 是支持多事务并发执行的,否则来一个请求处理一个请求,处理一个人请求的时候,别的人都等着,这网站就别做了,用户都要砸键盘了. 这里就有一个问题了:一个事务在写数据的时候,另一个事务要读这行数 ...

  6. 脏写、脏读、不可重复读、幻读的区别

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

  7. 关于脏写、脏读、不可重复读、幻读的理解

    1.概念: 脏写:如果一个事务修改了另一个未提交事务修改过的数据,那就意味着发生了脏写(事务A修改还未提交的事务B所修改的变量,一旦事务B执行回滚操作,那么事务A所做的操作就是无效的) 脏读:如果一个 ...

  8. 脏读(脏数据、脏页)、不可重复读、幻读

    一.脏读(读到未提交的数据) 在理解脏读之前,需要理解脏数据的概念. 脏数据是指事务对缓冲池中行记录的修改,并且还没有提交. 注意脏数据和脏页是完全不同的两种概念,脏页指的是在缓冲池中已经被修改的页, ...

  9. SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因...

    原本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需要有 SQL Server 事务和事务的隔离级别做基础铺垫.所以花了点时间,把 SQL Server 数据库中 ...

最新文章

  1. U盘中毒了?教你如何删除System Volume Information这个顽固文件夹
  2. 程序员看过来!高通漏洞赏金最高1.5万美金
  3. 【干货】从小米发布会看:雷军的七个产品思维
  4. asp.net之request获取数据
  5. 部署在Netweaver上的Fiori应用的WebContent文件夹
  6. oracle 分页查询
  7. exe打包工具哪个最好_一键分发工具哪个最好用?这款30万人都在用,很优秀!...
  8. 【微信插件】P3微信插件测试使用步骤
  9. 利用C#开发基于snmpsharpnet基础的SNMP开发应用
  10. python上机实验报告读取文件_Python程序设计实验八:文件
  11. 2012总结--第5篇--人脉篇
  12. 2个表 遍历 组合_7.2 图的存储结构(2)
  13. Infopath 2013 通过UserProfileService读取AD用户信息
  14. jQuery事件学习
  15. 【Android】五种常用布局方式详解(图文+示例)持续更新中...
  16. jsmind 线条_jsmind实例扩展(思维导图)
  17. 取消计算机用户密码页面,取消开机密码 Windows电脑开机登录界面取消方法-电脑教程...
  18. 百度地图迁徙大数据_百度地图迁徙大数据:北上广深城内出行年后首次大幅增长...
  19. 详述支付网关的设计原则
  20. 抖音微信登录服务器繁忙,微信登录抖音失败解决方法介绍

热门文章

  1. DataView 使用技巧 [转]
  2. gulimall——秒杀商品流程及优化(二)
  3. 解决 javasql.null, message from server: “Host ‘‘ is not allowed to connect to this MySQL server“
  4. 海贼王热血航线服务器维护,航海王热血航线1234区从今开始
  5. 第三方支付接口,安全稳定永远是第一位
  6. 【零售案例】阿里巴巴:Q1业绩强劲开端 新零售加速核心电商领先优势
  7. 在屏幕上输出以下图案: * *** ***** ******* ********* *********** ************* *********** ********* *******
  8. Android 插件化,qihoo360插件方案。集成简单实用方便,兼容性高
  9. Duplicate Symbol链接错的原因总结和解决方法
  10. JS逆向之某头条jsvmp逻辑层算法分析