关于innodb下,幻读是如何被解决的

简介: 关于innodb下,幻读是如何被解决的


innodb下幻读是如何在RR级别下被解决的?

先来简单的复习一下数据库隔离级别

  1. RU(Read Uncommitted)

一个事务A读取到另一个事务B未提交的修改,B回滚了,就造成了数据不一致。(现象:脏读)

  1. RC(Read Committed)

一个事务A在事务执行过程中第一次读取的值和第二次读取的值不一致,这是由于事务B在俩次读取之间修改了数据并提交了事务。(现象:不可重复读)

  1. RR(Repeatable Read)

一个事务A在事务执行过程中第一次读取的值和第二次读取的值一致(解决了不可重复读),但是其他事务B 的insert 或者 delete的操作,会影响到俩次查询的条数(现象:幻读)

  1. Serializable

最高的事务隔离级别,串行化。

问题来了:RR下会出现幻读,那为什么innodb能在RR下解决幻读呢?不是互相矛盾吗?

解释:这是由于innodb和标准不一致导致的。具体可以看看github火热的讨论Innodb RR 下能否防止幻读?

结论:RR 下,innodb下的幻读是由MVCC 或者 GAP 锁 或者是next-key lock 解决的。

关于MVCC 可以查看这篇文章 MVCC原理

意思就是MVCC判断了记录的可见性,比如 select count(*) from table where col_name = xxx 时(属于快照读),在RR 级别下,这条事务在事务一开始就生成了readview,通过这个readview 这条语句将会找到符合条件的行并且计算数量。 那么关于与如何找到这些符合条件的行,满足where 条件的同时也得满足本事务对这些行的可见性。 所以在同一事务里并不会产生幻读的现象。

关于GAP 锁 可以查看这篇文章next-key lock

在这里我们需要了解 当前读快照读 的区别

  1. 快照读:简单的select操作,属于快照读,不加锁。 select * from table where ?;
  2. 当前读:特殊的读操作,插入/更新/删除操作,属于当前读,需要加锁。
    select * from table where ? lock in share mode;
    select * from table where ? for update;
    insert into table values (…);
    update table set ? where ?;
    delete from table where ?;

    所有以上的语句,都属于当前读,读取记录的最新版本。并且,读取之后,还需要保证其他并发事务不能修改当前记录,对读取记录加锁。其中,除了第一条语句,对读取记录加S锁 (共享锁)外,其他的操作,都加的是X锁 (排它锁)。

我们来以下倆段伪代码:

//code 1
beginTransaction
delete * from table where id = ?  (加了二级索引(不是唯一索引))
endTransaction
//code 2
beginTransaction
select count(*) from table where id = ? for update (加了二级索引(不是唯一索引))
endTransaction
复制代码
  1. code 1 的分析:
    由于delete * from table where id = ? 这是当前读,它会锁定一个范围采用GAP 锁的方式,让符合条件的范围内不得让其他事务插入数据,这样也就解决了幻读。
  2. code 2 的分析:
    由于select count(*) from table where id = ? for update 虽然也是当前读,但是它加的锁是next-key-lock,它是由GAP锁和record锁组成的,所以它也能锁定范围不让其它事务插入符合条件的数据,锁定记录本身,也不让其它事务修改数据。这样也就避免了幻读


目录
相关文章
|
机器学习/深度学习 数据采集 人工智能
机器学习实战 | SKLearn入门与简单应用案例
本篇内容介绍了SKLearn的核心板块,并通过SKLearn自带的数据集,讲解一个典型应用案例。
1460 0
机器学习实战 | SKLearn入门与简单应用案例
|
消息中间件 存储 负载均衡
RocketMQ 面试题及答案整理,最新面试题
RocketMQ 面试题及答案整理,最新面试题
1833 4
|
Java 编译器
解密Java多线程中的锁机制:CAS与Synchronized的工作原理及优化策略
解密Java多线程中的锁机制:CAS与Synchronized的工作原理及优化策略
|
1月前
|
安全
一文搞懂synchronized锁的升级过程
synchronized锁的升级过程包括偏向锁、轻量锁和重量级锁。偏向锁在无竞争时可重复使用,轻量锁通过CAS自旋实现多线程竞争,重量级锁则会导致线程阻塞,涉及用户态到内核态的切换。CAS(比较并交换)用于实现乐观锁,保证原子性操作,但可能引发CPU资源浪费。文中还展示了手写锁的升级实现代码。
|
10月前
|
消息中间件 存储 运维
2024最全RabbitMQ集群方案汇总
本文梳理了RabbitMQ集群的几种方案,主要包括普通集群、镜像集群(高可用)、Quorum队列(仲裁队列)、Streams集群模式(高可用+负载均衡)和插件方式。重点介绍了每种方案的特点、优缺点及适用场景。搭建步骤包括安装Erlang和RabbitMQ、配置集群节点、修改hosts文件、配置Erlang Cookie、启动独立节点并创建集群,以及配置镜像队列以提高可用性和容错性。推荐使用Quorum队列与Streams模式,其中Quorum队列适合高可用集群,Streams模式则同时支持高可用和负载均衡。此外,还有Shovel和Federation插件可用于特定场景下的集群搭建。
2053 2
|
12月前
|
Web App开发 前端开发 程序员
将微信公众号文章同步到阿里云开发者社区
本文介绍了一种通过自己拓展的浏览器插件,便捷地将微信公众号文章同步到阿里云开发者社区的方法。
220 6
|
监控 安全 Java
Java与物联网:连接与控制设备
Java与物联网:连接与控制设备
1098 0
|
消息中间件 存储 算法
RocketMQ核心知识点整理,收藏再看!
RocketMQ核心知识点整理,收藏再看!
1264 0
RocketMQ核心知识点整理,收藏再看!
|
SQL 关系型数据库 MySQL
京东面试:什么情况下 mysql RR不能解决幻读? RR隔离mysql如何实现?
老架构师尼恩在其读者交流群中分享了关于MySQL事务隔离级别的深入解析,特别针对RR级隔离如何解决幻读问题进行了详细讨论。文章不仅解释了ACID中的隔离性概念,还列举了四种事务隔离级别(未提交读、提交读、可重复读、串行读)的特点及应用场景。尼恩通过具体的例子和图表,清晰地展示了不同隔离级别下的并发事务问题(脏读、不可重复读、幻读)及其解决方案,特别是RR级隔离下的MVCC机制如何通过快照读和当前读来防止幻读。此外,尼恩还提供了相关面试题的解答技巧和参考资料,帮助读者更好地准备技术面试。更多详细内容和实战案例可在《尼恩Java面试宝典》中找到。