首页 > 数据库 >MySQL幻读问题

MySQL幻读问题

时间:2024-01-27 17:46:01浏览次数:38  
标签:事务 快照 幻读 tp 查询 问题 MySQL SELECT

幻读指的是一个事务开启之后,执行了两次相同的 SELECT 查询某一范围内的数据,但是第二次查询返回了第一次未返回的行,也就是读取到了幻行,这就是幻读问题。

MySQL 官方也将这个问题叫做幻象问题,读取到的行叫做幻行。
地址:https://dev.mysql.com/doc/refman/8.0/en/innodb-next-key-locking.html

如何解决幻读问题?

在默认的可重复读(RR)隔离级别下:
针对快照读,InnoDB 通过 MVCC 的方式解决幻读问题,原理就是在事务开始之前就会生成一个 ReadView ,后续的查询都是基于这个 ReadView 进行的。

注意:如果在快照读期间执行了当前读,则 ReadView 会失效,进而产生幻读问题。

针对当前读,InnoDB 通过 Next-key Lock 解决幻读问题,原理就是 InnoDB 不止锁定查询中涉及的行,还会对索引结构中的间隙进行锁定,防止幻行被插入。

快照读:读取某一时刻生成的最新快照数据,即普通的 SELECT 语句,例如 SELECT * FROM t WHERE xx = yy
当前读:读取最新提交的数据,即 UPDATE、INSERT 、DELETE 以及 SELECT ... FOR UPDATE 的语句。

在串行化(SERIALIZABLE)隔离级别下:该隔离级别通过强制事务按序执行,使得不同事务之间不可能产生冲突,从而解决了幻读问题。

为什么可重复读隔离级别下的 MVCC没法彻底的解决幻读问题?

MVCC 解决幻读主要是针对快照读而言的,但是如果在快照读期间执行了当前读,比如 UPDATE、INSERT、DELETE、SELECT ... FOR UPDATE 等操作,那么快照读的 ReadView 就会失效,此时当前读会去读取最新的数据,进而产生幻读问题。
案例一:
当前表 tp 的数据如下所示:
image.png
事务 A 的操作

BEGIN;
#执行快照读
SELECT * FROM tp WHERE id = 5; #没数据

...执行事务B

#执行当前读,尝试更新id=5的数据
UPDATE tp SET age = 500 WHERE id = 5;

#执行快照读,再次查询id=5的数据
SELECT * FROM tp WHERE id = 5; #查询到了数据,此时事务还没提交哦!两次查询的结果不一样,发生了幻读。
.........
COMMIT;

事务 B 的操作

BEGIN;
#插入一条数据
INSERT INTO tp VALUE(5,50)
COMMIT;

案例二:
当前表 tp 的数据如下所示:
image.png
事务 A 的操作

BEGIN;
#执行快照读,查询年龄大于10的所有数据,查询到20,30,40三条数据
SELECT * FROM tp WHERE age > 10;

....事务B执行

#执行当前读,依旧查询年龄大于10的所有数据
SELECT * FROM tp WHERE age > 10 FOR UPDATE;
竟然把事务B刚插入的数据(5,50)也查询到了,发生了幻读。

....
COMMIT;

事务 B 的操作

BEGIN;
#插入数据
INSERT INTO tp VALUE(5,50);
COMMIT;

标签:事务,快照,幻读,tp,查询,问题,MySQL,SELECT
From: https://www.cnblogs.com/wangjiawu/p/17991705

相关文章

  • MVC 新手经常遇到的问题强调
    MVC新手经常遇到的问题强调1.前端相对地址、网站相对地址问题 2.前缓存问题 3.修改View重启问题 4.控制器重命名问题Asp.NetMvc控制器重名问题整理 5.  更多:Asp.Net自定义设置Http缓存示例(一)Asp.NetMvc控制器重名问题整理Asp.NetMvc表单提交之List集......
  • 2、【实操】dash库设计web界面对mysql数据进行展示
    dash+mysql的简单应用python库简介:  dash:web界面的UI设计;  pymysql:MySQL数据库连接、操作引擎pandas:使用read.sql("sql",mysql_connection)函数将msyql的表单数据转换成DataFrame格式 第一步:  实现对MySQL数据库的连接,并对表单的数据进行展示    ......
  • Dos命令 Mysql数据定时备份和删除7前的文件
    一、dos 命令Mysql 数据本地和异地备份@echooff::以下1~8参数请按自己的情况修改;其他的不需要修改::=======================视各环境情况修改=================::1,备份目标主机setdbhost=127.0.0.1::2,数据库端口setdbport=3306::3,本地MYSQL的bin路径setmysq......
  • 你好, 2023,最该问自己的7个问题
    适合打印下来放在日历上7个简单问题,快速反思2022,让2023勇往直前1.被"炒鱿鱼"收获成功需要不断分析什么有用,什么无用假如能掌控人生,要想更加成功,该放弃什么,开始什么,这两者间,什么在阻挡你?假如能掌控人生,从今天开始,我会立刻停止哪些事情?2.增加与减少享受爬山的过程,自然能登顶什么能......
  • 请教问题,layui step 这个分步表单的高度怎么自适应
    ​​这里设置height:auto是不显示的  指定高度是可以显示的这是那个步骤条配置`//步骤条配置layui.config({base:'./step-lay/'}).use(['form','step'],function(){var$=layui.$,form=layui.form,st......
  • MySQL 运算符
    本章节我们主要介绍MySQL的运算符及运算符的优先级。MySQL主要有以下几种运算符:算术运算符MySQL支持的算术运算符包括:运算符 作用加法– 减法乘法/或DIV 除法%或MOD 取余在除法运算和模运算中,如果除数为0,将是非法除数,返回结果为NULL。1、加mysql>select......
  • Java服务通过动态开关 Profiling 实现关键问题定位-故障定位
    作者观测云高级技术专家深圳办公室黄小龙简介Profile通过收集和分析应用程序运行过程中CPU、内存和I/O相关的数据,可以识别应用程序的性能瓶颈和错误,帮助我们更好地了解程序的运行情况。Profile是一种非常有价值的技术,通过Profile可以实现:识别性能瓶颈:Profiling可以帮......
  • 可重入锁的含义及解决的问题
    可重入锁顾名思义可以重复利用的锁,但不是任何方法都能重复使用,而是最初占有锁的方法调用的方法,即是调用方法与被调方法可以同时占用同一把锁。下面从三个角度来说明:1.被调方法没有加锁publicclassLockTest{privatestaticfinalObjectobj=newObject();publicv......
  • MySQL 处理重复数据
    有些MySQL数据表中可能存在重复的记录,有些情况我们允许重复数据的存在,但有时候我们也需要删除这些重复的数据。本章节我们将为大家介绍如何防止数据表出现重复数据及如何删除数据表中的重复数据。防止表中出现重复数据你可以在MySQL数据表中设置指定的字段为PRIMARYKEY(主......
  • MySQL 序列使用AUTO_INCREMENT
    MySQL序列是一组整数:1,2,3,…,由于一张数据表只能有一个字段自增主键,如果你想实现其他字段也实现自动增加,就可以使用MySQL序列来实现。本章我们将介绍如何使用MySQL的序列。使用AUTO_INCREMENTMySQL中最简单使用序列的方法就是使用MySQLAUTO_INCREMENT来定义列。实例......