问题引出

我之前的一篇博客 数据库并发不一致分析 有提到过事务隔离级别以及相应加锁方式、能够解决的并发问题。

标准情况下,在 RR(Repeatable Read) 隔离级别下能解决不可重复读(当行修改)的问题,但是不能解决幻读的问题。

而之前有看过一篇 mysql 加锁的文章 MySQL 加锁处理分析,里面有提到一点:

对于Innodb,Repeatable Read (RR) 针对当前读,RR隔离级别保证对读取到的记录加锁 (记录锁),同时保证对读取的范围加锁,新的满足查询条件的记录不能够插入 (间隙锁),不存在幻读现象。

那么问题来了,到底 Innodb 中 RR 隔离级别是否能解决幻读呢?

在 MySQL 加锁处理分析这篇文章下面的评论中,有这样的一个交流:

ontheway
弱弱地问一句,我看的书里面都说的是RR隔离级别不允许脏读和不可重复读,但是可以幻读,怎么和作者说的不一样呢?

hedengcheng(作者)
你说的没错,因此我在文章一开始,就强调了这一点。mysql innodb引擎的实现,跟标准有所不同。

求证官方文档

MySQL Innodb 引擎的实现,跟标准有所不同,针对这个问题,我表示怀疑,于是查看 mysql 官方文档关于 RR的解释,里面有这么一段话:

For locking reads (SELECT with FOR UPDATE or LOCK IN SHARE MODE), UPDATE, and DELETE statements, locking depends on whether the statement uses a unique index with a unique search condition, or a range-type search condition. For a unique index with a unique search condition, InnoDB locks only the index record found, not the gap before it. For other search conditions, InnoDB locks the index range scanned, using gap locks or next-key locks to block insertions by other sessions into the gaps covered by the range.

大致意思就是,在 RR 级别下,如果查询条件能使用上唯一索引,或者是一个唯一的查询条件,那么仅加行锁,如果是一个范围查询,那么就会给这个范围加上 gap 锁或者 next-key锁 (行锁+gap锁)。

从这句话的理解来看,和文章里的解释一样,由于 RR 级别对于范围会加 GAP 锁,这个和 sql 的标准是有一些差异的。

其他解释

后面又发现了一篇文章 Understanding InnoDB transaction isolation levels,文章中又提到:

This isolation level is the default for InnoDB. Although this isolation level solves the problem of non-repeatable read, but there is another possible problem phantom reads.

大概意思是,RR 能解决不可重复读的问题,但仍可能发生幻读,怀疑作者并不了解 Innodb 的特殊实现,评论中也有提到:

Do you mean 'write skew' instead of 'phantom reads'? The 'repeatable read' in SQL standard allows 'phantom reads', however, since InnoDB uses next-key locking this anomaly does not exist in this level. Looks like it's equivalent to 'snapshot isolation' in Postgres and Oracle.

再来看一篇文章 MySQL的InnoDB的幻读问题,这里面提供了一些例子,还没来得及分析,但最后的结论是:

MySQL InnoDB的可重复读并不保证避免幻读,需要应用使用加锁读来保证。而这个加锁度使用到的机制就是next-key locks。

最终结论

Innodb 的 RR 隔离界别对范围会加上 GAP,理论上不会存在幻读,但是是否有例外呢,这个还需要进一步求证。

Innodb 中 RR 隔离级别能否防止幻读?的更多相关文章

  1. InnoDB MVCC RR隔离级别下的数据可见性总结

    一.背景 熟悉数据库隔离级别的人都知道,在RR(可重复读)隔离级别下,无论何时多次执行相同的SELECT快照读语句,得到的结果集都是完全一样的,即便两次SELECT语句执行期间,其他事务已经改变了该查 ...

  2. InnoDB在MySQL默认隔离级别下解决幻读

    1.结论 在RR的隔离级别下,Innodb使用MVVC和next-key locks解决幻读,MVVC解决的是普通读(快照读)的幻读,next-key locks解决的是当前读情况下的幻读. 2.幻读 ...

  3. MYSQL事件隔离级别以及复读,幻读,脏读的理解

    一.mysql事件隔离级别 1未提交读(READUNCOMMITTED) 另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据(脏读)( 隔离级别最低,并发性能高 ) 2 ...

  4. 数据库事务中的隔离级别和锁+spring Transactional注解

    数据库事务中的隔离级别和锁 数据库事务在后端开发中占非常重要的地位,如何确保数据读取的正确性.安全性也是我们需要研究的问题.ACID首先总结一下数据库事务正确执行的四个要素(ACID): 原子性(At ...

  5. [转]数据库事务中的隔离级别和锁+spring Transactional注解

    数据库事务中的隔离级别和锁 数据库事务在后端开发中占非常重要的地位,如何确保数据读取的正确性.安全性也是我们需要研究的问题.ACID首先总结一下数据库事务正确执行的四个要素(ACID): 原子性(At ...

  6. (7)MySQL进阶篇SQL优化(InnoDB锁-事务隔离级别 )

    1.概述 在我们在学习InnoDB锁知识点之前,我觉得有必要让大家了解它的背景知识,因为这样才能让我们更系统地学习好它.InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION ...

  7. [原创]java WEB学习笔记78:Hibernate学习之路---session概述,session缓存(hibernate 一级缓存),数据库的隔离级别,在 MySql 中设置隔离级别,在 Hibernate 中设置隔离级别

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  8. SQL Server与Oracle中的隔离级别

    在SQL92标准中,事务隔离级别分为四种,分别为:Read Uncommitted.Read Committed.Read Repeatable.Serializable 其中Read Uncommi ...

  9. MySQL的可重复读级别能解决幻读吗

    引言 之前在深入了解数据库理论的时候,了解到事物的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了.但是对于幻 ...

随机推荐

  1. 使用JAX-WS(JWS)发布WebService(一)

    JAX-WS概述: 通过Main发布一个简单WebService: JAX-WS(Java API for XML Web Services)规范是一组XML web services的JAVA AP ...

  2. 在vue项目中添加eslint规则

    自己配置脚手架时候如何安装eslint语法规则, 第一步安装 官方推荐的安装包如下 eslint eslint-config-standard eslint-plugin-standard eslin ...

  3. 【Hutool】Hutool工具类之String工具——StrUtil

    类似的是commons-lang中的StringUtils 空与非空的操作——经典的isBlank/isNotBlank.isEmpty/isNotEmpty isBlank()——是否为空白,空白的 ...

  4. geoserver中WMS服务详细说明

    官方geoserver中WMS服务中几种操作的API的详细说明地址: http://docs.geoserver.org/stable/en/user/services/wms/reference.h ...

  5. python字符串的方法介绍

    博文取自鱼C论坛文章: http://bbs.fishc.com/forum.php?mod=viewthread&tid=38992&extra=page%3D1%26filter% ...

  6. C++中的引用常见用法

    1.引用的内涵 引用就是给变量取外号而已. 2.四种不能使用引用的情况 void &r=x; //不能建立void类型引用 int &&r=x; //不能建立引用的引用 int ...

  7. vs2015 mvc项目数据迁移报错

    第一次做个mvc项目玩玩,然后需要数据迁移,也没做过,就百度找怎么数据迁移, 找到的方法是: 如果数据是在类库项目里就在‘程序包管理控制台’输入:enable-migrations -ContextT ...

  8. Linux命令应用大词典-第5章 显示文本和文件内容

    5.1 cat:显示文本文件 5.2 more:分页显示文本文件 5.3 less:回卷显示文本文件 5.4 head:显示指定文件前若干行 5.5 tail:查看文件末尾数据 5.6 nl:显示文件 ...

  9. (C#)原型模式—深复制与浅复制

    1.原型模式 用原型实例指定创建对象的实例,并且通过拷贝这些原型创建新的对象. *原型模式隐藏了创建对象的细节,提高了性能. *浅复制:被复制对象的所有变量都含有与原来对象相同的值,而且所有对其他对象 ...

  10. lintcode: Missing String

    Missing String  描述: Given two strings, you have to find the missing string. Have you met this questi ...