什么是幻读

幻读表示的是在一个事物里面 同一个select语句,前后两次查询出来的结果是不相同的,需要注意的一点是,在InnoDB里面,幻读跟事物的隔离级别有关,更加准确的说是跟一个事物的快照和当前读有关

下面是在Mysql8.0.11版本下进行幻读的复现:引擎:InnoDB

事物隔离级别:Read Commited

MVCC和快照读以及当前读

MVCC

在介绍MVCC之前先来介绍下MVCC为什么会出现,首先数据库作为一个数据存储工具,那么肯定是存在并发的情况,

在Mysql的InnoDB里面最常见的就是x锁,这是一种写锁,在并发的情况下只有一个事务会获取该锁,其他事务则会一直等待直至获取到该锁。

那么在读取的时候如何保证并发的事物都能正确的读取到自己正确的数据呢?

在MVCC的概念里面,如果事务的隔离级别是Read Commited的话,那么每一次的快照都都会读取该行的最近一次commited数据,而如果是Repeatable Read的话,则是会读取当前事务ID开始之前的一次commited数据。

所以MVCC仅仅是作为一个保证数据库并发读情况下的一个数据正确的手段而已,在不同的数据库里面,有不同的实现,例如在OceanBase里面,是通过操作链来解决并发读的问题

快照读

快照读是利用MVCC和 undo log 来实现的,其主要作用就是当我们对某行数据修改之后,并不会将原值修改,而是在上一个版本上面再新建一个版本(修改InnoDB的隐藏两列)。

所以在不同的隔离级别下,可以根据自己的事物ID来获取自己所需要的数据。当第一条不满足的时候,会沿着undo log一直寻找,在Read Commited隔离级别下就是直接找出该行数据最后一次提交的版本

当前读

当前读是对数据的加锁读取,读取的都是最新的数据,例如如下SQL:1

2

3

4

5

6select ... for update

select ... in share mode

insert

update

delete

...

同时也需要注意的一点是,当前读会对涉及到的行都进行加锁

为什么会有当前读和快找读

按照Mysql官方的解释,当前读是为了防止其他事物修改你即将进行的操作If you query data and then insert or update related data within the same transaction, the regular SELECT statement does not give enough protection. Other transactions can update or delete the same rows you just queried. InnoDB supports two types of locking reads that offer extra safety

幻读发生的条件

首先解释下Mysql官方对于幻读的解释:The so-called phantom problem occurs within a transaction when the same query produces different sets of rows at different times. For example, if a SELECT is executed twice, but returns a row the second time that was not returned the first time, the row is a “phantom” row.

这里Mysql官方虽然只是给出了对于幻行的定义,但是仍然可以简单解释下,也就是说两次的select前后得到的结果集是不同的,那么新多出来的一行就可以称之为幻行

在这里特别需要注意的是,在PR隔离界别下,只有当前读才会出现幻读

Read Commited

在Read Commited隔离级别下,每一次的select 都是一次快照读,所以在该隔离级别下,幻读可以在快照读和当前读发生。事务一1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27mysql> set session transaction isolation level read committed;

Query OK, 0 rows affected (0.00 sec)

mysql> START TRANSACTION;

Query OK, 0 rows affected (0.00 sec)

mysql> begin;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from szh.t1

-> ;

+---------+-----------+

| area_id | order_num |

+---------+-----------+

| 1 | 22 |

| 2 | 10 |

+---------+-----------+

2 rows in set (0.00 sec)

mysql> select * from `szh`.`t1`;

+---------+-----------+

| area_id | order_num |

+---------+-----------+

| 1 | 22 |

| 2 | 10 |

+---------+-----------+

2 rows in set (0.00 sec)事务二1INSERT INTO `szh`.`t1`(`area_id`, `order_num`) VALUES (3, 22);

此时事务一再进行select1

2

3

4

5

6

7

8

9mysql> select * from `szh`.`t1`;

+---------+-----------+

| area_id | order_num |

+---------+-----------+

| 1 | 22 |

| 2 | 10 |

| 3 | 22 |

+---------+-----------+

3 rows in set (0.00 sec)

于是幻读发生了

Repeatable Read

那么如果在Repeatable Read隔离级别下,上面的SQL在执行一遍会出现什么情况呢?事务一1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18mysql> START TRANSACTION;

Query OK, 0 rows affected (0.00 sec)

mysql> begin;

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM `t1`

-> ;

+---------+-----------+

| area_id | order_num |

+---------+-----------+

| 1 | 22 |

| 2 | 10 |

| 3 | 22 |

| 4 | 33 |

| 5 | 55 |

+---------+-----------+

5 rows in set (0.00 sec)事务二1INSERT INTO `szh`.`t1`(`area_id`, `order_num`) VALUES (6, 66);事务一再次select1

2

3

4

5

6

7

8

9

10

11mysql> SELECT * FROM `t1`;

+---------+-----------+

| area_id | order_num |

+---------+-----------+

| 1 | 22 |

| 2 | 10 |

| 3 | 22 |

| 4 | 33 |

| 5 | 55 |

+---------+-----------+

5 rows in set (0.00 sec)

可以看到的是在快照读下面,是没有幻读出现的,那么修改select为当前读呢?

在事务一里面再次执行以下SQL1

2

3

4

5

6

7

8

9

10

11

12mysql> SELECT * FROM `t1` for update;

+---------+-----------+

| area_id | order_num |

+---------+-----------+

| 1 | 22 |

| 2 | 10 |

| 3 | 22 |

| 4 | 33 |

| 5 | 55 |

| 6 | 66 |

+---------+-----------+

6 rows in set (0.00 sec)

可以看到确实出现了两次的select不同的情况。

所以需要强调一点的是,在Repeatable Read隔离级别下,只有当前读才会出现幻读,因为在该级别下,快照读是从begin开始的第一个普通select建立的Read View,以后的普通select都是基于第一次的select,自然而然不会出现幻读了

mysql 什么是幻读_Mysql中的幻读(一)相关推荐

  1. MySQL读已提交有间隙锁吗_mysql中的幻读与间隙锁

    一.数据库隔离级别 一般来讲,数据库的隔离级别分为读未提交.读已提交(read commit,rc).可重复读(read reapeat,rr).串行化四个级别.在mysql中默认隔离级别是rr.读未 ...

  2. mysql数据库出现幻读_MySQL中幻读和幻读存在的问题

    1.概念 幻读指的是一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行. 可以看到,session A里执行了三次查询,分别是Q1.Q2和Q3.它们的SQL语句相同,都是s ...

  3. mysql 事务隔离详解_MySQL 中事务、事务隔离级别详解

    一.事务的概念 1.事务的概念 2.在mysql中哪些存储引擎(表类型)支持事务哪些不支持 3.事务的四个属性 4.mysql事务的创建与存在周期 5.mysql行为 6.事务的隔离性和性能 7.my ...

  4. mysql不同连接的事务_mysql中不同事务隔离级别下数据的显示效果--转载

    事务是一组原子性的SQL查询语句,也可以被看做一个工作单元.如果数据库引擎能够成功地对数据库应用所有的查询语句,它就会执行所有查询,如果任何一条查询语句因为崩溃或其他原因而无法执行,那么所有的语句就都 ...

  5. mysql的explain怎么看_mysql中explain用法详解

    如果在select语句前放上关键词explain,mysql将解释它如何处理select,提供有关表如何联接和联接的次序. explain的每个输出行提供一个表的相关信息,并且每个行包括下面的列: 1 ...

  6. mysql排他锁怎么用_MySQL 中的共享锁和排他锁的用法

    在 MySQL 中的行级锁.表级锁和页级锁中,咱们介绍过,行级锁是 MySQL 中锁定粒度最细的一种锁,行级锁能大大减少数据库操作的冲突.行级锁分为共享锁和排他锁两种,本文将详细介绍共享锁和排他锁的概 ...

  7. mysql去除select换行符_MySQL中去除字段中的回车符和换行符

    问题: 在使用[ load data infile 'D:/node.txt' into table node fields terminated by '\t'; ]语句批量导入如下图所示的aaa. ...

  8. mysql创建临时表 主键_MySQL中临时表的基本创建与使用教程

    当工作在非常大的表上时,你可能偶尔需要运行很多查询获得一个大量数据的小的子集,不是对整个表运行这些查询,而是让MySQL每次找出所需的少数记录,将记录选择到一个临时表可能更快些,然后在这些表运行查询. ...

  9. mysql 子查询怎么写_MySQL中两种子查询的写法

    MySQL的测试环境 测试表如下 create table test_table2 ( id int auto_increment primary key, pay_id int, pay_time ...

最新文章

  1. Java线程池理解及用法
  2. [Linux程序设计][调试][ElectricFence]
  3. jzoj3500-物语【最短路】
  4. 排除IIS特殊管理困惑
  5. 眼儿媚·迟迟春日弄轻柔 [宋] 朱淑真
  6. SQLServer-Error Log
  7. 从荣耀小米扎堆“滑盖全面屏”,看国产手机的“取巧”式创新
  8. 看半小时漫画,通晓计算机基础
  9. windows上java调用gdal.jar报错
  10. php 判断语句是一个作用域吗,关于php变量作用域的详细介绍_后端开发
  11. JMeter并发测试工具
  12. 解读SPSS多元方差分析中的多因素多变量的相互影响
  13. java pdf合并_如何实用Java实现合并、拆分PDF文档
  14. ADS1115使用之电路与程序
  15. pdf会签_图纸会签规定
  16. ubuntu 下如何调节显卡风扇转速?
  17. Maya10个非常实用的操作技巧,让你轻松玩转Maya
  18. 计算机打印机无法共享怎么设置密码,打印机共享设置密码【调解思路】
  19. 最美圣诞树,用Python画棵雪夜圣诞树送给你
  20. Python实现门禁管理系统(源码)

热门文章

  1. ros通过程序的方式发布导航的目标点
  2. 美少女养成记---根据月日计算星座
  3. TreeView节点设置图标
  4. exercise13 モーツァルト
  5. 蒸妙发展的奇妙“5+N”故事擅长将合作方变股东
  6. STM32菜鸟成长记录---系统滴答定时器(systick)应用
  7. echarts CDN 地址
  8. windows 10预览版升级win10 7月29 10240.16384
  9. 火山应用系列之炫彩模块自制【信息框】
  10. 九齐单片机 , 使用了未定义的符号“STK03”(13010) ,取正 / 符号出错