文章目录

  • MySQL数据库读现象
  • 一、数据库的读现象
    • 1、脏读(dirty read):读取未提交数据
    • 【案列详解】
    • 2、不可重复读取 (nonrepeatable read):前后多次读取,数据内容不一致
    • 【案列详解】
    • 3、幻读(nonrepeatable read):前后多次读取,数据总量不一致
    • 【案列详解】
  • 二、不可重复读与幻读之间的区别
  • 三、事务的隔离级别
    • 1、读未提交(READ UNCOMMITTED)
    • 2、读已提交(READ COMMITTED)
    • 3、可重复读(REPEATABLE READ)
    • 4、可串行化(SERIALIZABLE)
    • 5、隔离级别的实现原理
  • 四、解决方案
    • 【MySQL解决幻读】
      • 【多版本控制(MVCC)的原理】
      • 【Next-Key锁(当前读)的原理】

MySQL数据库读现象

一、数据库的读现象

数据库管理软件的“读现象”指的是当多个事务并发执行时,在读取数据方面可能碰到的问题,包括有脏读、不可重复读和幻读

#读现象对于一些数据库管理软件会自带相应的机制去解决脏读、不可重复读、幻读等问题,因为这些自带的机制,下述的一些实验现象可能在某一数据库管理软件的默认机制下并不成立,即我们并不能在所有数据库管理软件中看到所有的读现象。所以此处我们暂且抛开具体的某个数据库管理软件的默认机制的干扰,暂时假设没有附加任何机制为前提,单纯地去理解数据库的读现象

1、脏读(dirty read):读取未提交数据

一个事务读到了另一个未提交事务修改过的数据

会话B开启一个事务,把id=1的name为武汉市修改成温州市,此时另外一个会话A也开启一个事务,读取id=1的name,此时的查询结果为温州市,会话B的事务最后回滚了刚才修改的记录,这样会话A读到的数据是不存在的,这个现象就是脏读。(脏读只在读未提交隔离级别才会出现)

脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据

【案列详解】

事务一:查询一条记录, id 为 2 的 age 为 18
事务一:查询后,事务二对该条数据进行了 age=22 的更改, 但是没有进行提交
事务一:有进行查询操作, 查询到修改后的记录 age=22
事务二:进行了回滚操作, 记录中就没有了 id=2, age=22 的记录了, 所以, 事务1读到了一条脏数据(也叫无效数据)

2、不可重复读取 (nonrepeatable read):前后多次读取,数据内容不一致

是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。(即不能读到相同的数据内容)

一个事务只能读到另一个已经提交的事务修改过的数据,并且其他事务每对该数据进行一次修改并提交后,该事务都能查询得到最新值。(不可重复读在读未提交和读已提交隔离级别都可能会出现)

会话A开启一个事务,查询id=1的结果,此时查询的结果name为武汉市。接着会话B把id=1的name修改为温州市(隐式事务,因为此时的autocommit为1,每条SQL语句执行完自动提交),此时会话A的事务再一次查询id=1的结果,读取的结果name为温州市。会话B再此修改id=1的name为杭州市,会话A的事务再次查询id=1,结果name的值为杭州市,这种现象就是不可重复读

例如,一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可重复。如果只有在作者全部完成编写后编辑人员才可以读取文档,则可以避免该问题

【案列详解】

事务一:查询一条 id=2 的记录
事务二:随之对 id 为 2 的记录进行了更改, 并且进行了提交
事务一:再次查询 id=2 的记录, 发现第二次查询的记录已经发生了改变, 这个就叫做不可重复读#在基于锁的并发控制中不可重复读现象发生在当执行 select 操作时没有获得读锁(read locks)或者 select 操作执行完后马上释放了读锁; 多版本并发控制中当没有要求一个提交冲突的事务回滚也会发生不可重复读现象

3、幻读(nonrepeatable read):前后多次读取,数据总量不一致

幻读是不可重复读的一种特殊情况, 当事务没有获取范围锁的情况下执行 select 操作可能会发生幻读现象

一个事务先根据某些条件查询出一些记录,之后另一个事务又向表中插入了符合这些条件的记录,原先的事务再次按照该条件查询时,能把另一个事务插入的记录也读出来。(幻读在读未提交、读已提交、可重复读隔离级别都可能会出现)

会话A开启一个事务,查询id>0的记录,此时会查到name=武汉市的记录。接着会话B插入一条name=温州市的数据(隐式事务,因为此时的autocommit为1,每条SQL语句执行完自动提交),这时会话A的事务再以刚才的查询条件(id>0)再一次查询,此时会出现两条记录(name为武汉市和温州市的记录),这种现象就是幻读

一般解决幻读的方法是增加范围锁RangeS,锁定检锁范围为只读,这样就避免了幻读
事务一执行了两次相同的查询操作。但是两次操作中间事务二向数据库中增加了一条符合事务一的查询条件的数据,导致幻读

【案列详解】

事务一:读取或修改了指定 where 子句过滤出来的结果集
事务二:插入了一条新记录, 并且该条记录满足 where 子句的过滤条件
事务一:使用相同的查询再次进行检索, 发现看到了事务二刚刚插入的记录, 但刚刚明明已经使用 where 子句过滤修改了这些记录, 就好像"幻觉’'一样, 这对于事务一来说是突然出现的, 这就是幻读

二、不可重复读与幻读之间的区别

幻读和不可重复读都是指的一个事务范围内的操作受到其他事务的影响
区别:幻读是重点在插入和删除,不可重复读重点在修改

1)#~~不可重复读~~ 是读取了其他事务更改的数据,针对update操作
解决:使用行级锁,锁定该行,事务A多次读取操作完成后才释放该锁,这个时候才允许其他事务更改刚才的数据。2)#~~幻读~~ 是读取了其他事务新增的数据,针对insert与delete操作
解决:使用表级锁,锁定整张表,事务A多次读取数据总量之后才释放该锁,这个时候才允许其他事务新增数据。

三、事务的隔离级别

MySQL的事务隔离级别一共有四个,分别是读未提交、读已提交、可重复读以及可串行化

MySQL的隔离级别的作用就是让事务之间互相隔离,互不影响,这样可以保证事务的一致性。
隔离级别比较:可串行化>可重复读>读已提交>读未提交
隔离级别对性能的影响比较:可串行化>可重复读>读已提交>读未提交

由此看出,隔离级别越高,所需要消耗的MySQL性能越大(如事务并发严重性),为了平衡二者,一般建议设置的隔离级别为可重复读,MySQL默认的隔离级别也是可重复读

1、读未提交(READ UNCOMMITTED)

在读未提交隔离级别下,事务A可以读取到事务B修改过但未提交的数据。
可能发生脏读、不可重复读和幻读问题,一般很少使用此隔离级别

2、读已提交(READ COMMITTED)


在读已提交隔离级别下,事务B只能在事务A修改过并且已提交后才能读取到事务B修改的数据
读已提交隔离级别解决了脏读的问题,但可能发生不可重复读和幻读问题,一般很少使用此隔离级别

3、可重复读(REPEATABLE READ)


在可重复读隔离级别下,事务B只能在事务A修改过数据并提交后,自己也提交事务后,才能读取到事务B修改的数据。
可重复读隔离级别解决了脏读和不可重复读的问题,但可能发生幻读问题。

提问:为什么上了写锁(写操作),别的事务还可以读操作?
因为InnoDB有MVCC机制(多版本并发控制),可以使用快照读,而不会被阻塞

4、可串行化(SERIALIZABLE)




各种问题(脏读、不可重复读、幻读)都不会发生,通过加锁实现(读锁和写锁)


5、隔离级别的实现原理

使用MySQL的默认隔离级别(可重复读)来进行说明。每条记录在更新的时候都会同时记录一条回滚操作(回滚操作日志undo log)。
同一条记录在系统中可以存在多个版本,这就是数据库的多版本并发控制(MVCC)。
即通过回滚(rollback操作),可以回到前一个状态的值

四、解决方案

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

所以这些问题的本质,都是数据库的多事务并发问题

那么为了解决多事务并发带来的脏读、不可重复读、幻读等读等问题,数据库才设计了锁机制、事务隔离机制、MVCC 多版本隔离机制,用一整套机制来解决多事务并发问题

【MySQL解决幻读】

在高并发的情况下,我们要保证数据的一致性和事务与事务之间的隔离性
1)多版本控制(MVCC)
2)Next-Key锁(当前读)

【多版本控制(MVCC)的原理】

InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的,这两个列分别保存了这个行的创建时间,一个保存的是行的删除时间。
这里存储的并不是实际的时间值,而是系统版本号(可以理解为事务的ID),每开始一个新的事务,系统版本号就会自动递增,事务开始时刻的系统版本号会作为事务的ID

【Next-Key锁(当前读)的原理】

将当前数据行与上一条数据和下一条数据之间的间隙锁定,保证此范围内读取数据是一致的

#Next-Key锁又分为两种:1)记录锁(Record Locks):加在索引上的锁,记录锁是 封锁记录,记录锁也叫行锁列:SELECT * FROM `test` WHERE `id`=1 FOR UPDATE;它会在 id=1 的记录上加上记录锁,以阻止其他事务插入,更新,删除 id=1 这一行记录锁、间隙锁、临键锁都是排它锁2)间隙锁(Gap Locks):加在索引之间的锁,间隙锁是封锁索引记录中的间隔,或者第一条索引记录之前的范围,又或者最后一条索引记录之后的范围

17@MySQL数据库读现象详解(脏读、幻读、不可重复读)相关推荐

  1. laravel 调试mysql_Laravel - MySQL数据库的使用详解3(Query Builder用法2:新增、修改、删除)...

    五.新增.修改.删除操作 在前文中我介绍了如何使用Query Builder(查询构造器)进行数据查询,下面接着介绍如何使用它进行数据的增.删.改操作.同样假设我们有如下用户表(user): 1,新增 ...

  2. MySQL 数据库 source 命令详解及实例

    MySQL 数据库 source 命令详解及实例 MySQL 数据库 source 命令,该命令是数据库导入命令.source 命令的用法非常简单,首先你需要进入 MySQL 数据库的命令行管理界面, ...

  3. linux系统——mysql数据库默认字符集详解

    linux系统--mysql数据库默认字符集详解 - mysql的字符集配置细化到四种 对数据库server配置 对库设置 对表设置 对列设置 - 对mysql-server设置 对server设置是 ...

  4. MySQL事务与锁详解,并发读异常与隔离策略

    文章目录 一.事务概念及ACID特性 二.隔离级别介绍 三.事务具体实现 3.1 undo log与redo log 3.2 MVCC 3.3 锁 3.3.1 粒度锁类型 3.2 锁算法介绍 四.并发 ...

  5. MySQL数据库count语句详解

    select count(*) 应该是一个比较常用的语句,用来统计记录行数. 但是,慢慢地你会发现,这个语句越来越慢了,为什么呢? count(*) 的实现方式 首先,我们来看下它的实现方式. MyS ...

  6. 【MySQL系列5】深入分析MySQL中锁并详解锁解决幻读问题

    MySQL锁分析 MySQL系列文章汇总 前言 什么是锁 锁的分类 全局锁 表锁 行锁 共享锁 排他锁 意向锁 各种锁的兼容关系 锁到底锁的是什么 举例猜测 结论 行锁的算法 记录锁(Record L ...

  7. dbeaver连接mysql 驱动jar_Jmeter(七) 从入门到精通 建立数据库测试计划实战lt;MySQL数据库gt;(详解教程)...

    1.简介 在实际工作中,我们经常会听到数据库的性能和稳定性等等,这些有时候也需要测试工程师去评估和测试,上一篇文章宏哥主要介绍了jmeter连接和创建数据库测试计划的过程,宏哥在文中通过示例和代码非常 ...

  8. mysql数据库安装最详解

    数据库的基本概念 当今主流的数据库 SQL Server (微软公司产品) Oracle (甲骨文公司产品) DB2 (IBM公司产品) MySQL (甲骨文公司收购) 什么是mysql数据库 MyS ...

  9. java连接mysql数据库方法_java连接mysql数据库的方法详解

    连接mysql数据库在java中有几种常用的方式有官方提供的JDBC连接MySQL数据库也有后面我们讲到的其它的方式连接数据库,具体如下. JDBC连接MySQL数据库 首先要下载Connector/ ...

最新文章

  1. mysql切换到使用openssl_OpenSSL可以用来调试到MySQL服务器的SSL连接吗?
  2. HTML label的隐藏,html – 带有可见的隐藏元素:after – CSS
  3. 社交游戏纳入文化部监管视野 开发者或出海
  4. Tensorflow实践 基本原理学习和框架使用
  5. 如何挽回一个快要“变心”的买家?(转自索菲外贸笔记)
  6. c++输出小数点后几位_2.1 怎么在屏幕上输出各种类型的数据
  7. 图5-5与代码中变量的对应关系
  8. linux家庭云服务器,linux服务器云(linux家用云服务器)
  9. 线性代数 —— 线性递推关系
  10. 手机驱动开发_新加坡科学家开发由智能手机驱动的无电池“智能服装”
  11. 马云宣布再捐赠800台呼吸机 用最快的速度送到欧洲国家一线医院
  12. Linux arm 下载程序,arm-linux—gcc如何下载安装
  13. 使用 JavaScript,也能在 Web 应用中实现人脸检测功能?!
  14. Win32最小的多用户Shell 1.2 506字节
  15. 自定义 UINavigationController
  16. 如何用网站统计工具追踪访客来路
  17. ftl模板文件编辑器
  18. DOM初探(17)——查看元素的尺寸与位置
  19. 微社区成为社交电商法宝的原因是什么?
  20. 国货百雀羚化妆品---大数据分析

热门文章

  1. CentOS 7 多硬盘合并 mergerfs 磁盘合并 + Duf 磁盘容量查看
  2. Visio用UML2.2模板包
  3. hydra笔记-利用hydra暴力破解ssh弱口令
  4. [源码解析] 深度学习分布式训练框架 horovod (11) --- on spark --- GLOO 方案
  5. 前端实现文件下载(a标签实现文件下载 避免直接打开问题)
  6. 一夜之间!京东市值涨350亿,拼多多涨550亿,阿里涨1400亿
  7. start with connect by prior用法
  8. 找素数(质数):线性筛法和埃氏筛法
  9. Excel如何将阿拉伯数字转为中文数字
  10. 一人点赞,N人跟风?