Innodb 中 RR 隔离级别能否防止幻读?
问题引出
我之前的一篇博客 数据库并发不一致分析 有提到过事务隔离级别以及相应加锁方式、能够解决的并发问题。
标准情况下,在 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 隔离级别能否防止幻读?的更多相关文章
- InnoDB MVCC RR隔离级别下的数据可见性总结
一.背景 熟悉数据库隔离级别的人都知道,在RR(可重复读)隔离级别下,无论何时多次执行相同的SELECT快照读语句,得到的结果集都是完全一样的,即便两次SELECT语句执行期间,其他事务已经改变了该查 ...
- InnoDB在MySQL默认隔离级别下解决幻读
1.结论 在RR的隔离级别下,Innodb使用MVVC和next-key locks解决幻读,MVVC解决的是普通读(快照读)的幻读,next-key locks解决的是当前读情况下的幻读. 2.幻读 ...
- MYSQL事件隔离级别以及复读,幻读,脏读的理解
一.mysql事件隔离级别 1未提交读(READUNCOMMITTED) 另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据(脏读)( 隔离级别最低,并发性能高 ) 2 ...
- 数据库事务中的隔离级别和锁+spring Transactional注解
数据库事务中的隔离级别和锁 数据库事务在后端开发中占非常重要的地位,如何确保数据读取的正确性.安全性也是我们需要研究的问题.ACID首先总结一下数据库事务正确执行的四个要素(ACID): 原子性(At ...
- [转]数据库事务中的隔离级别和锁+spring Transactional注解
数据库事务中的隔离级别和锁 数据库事务在后端开发中占非常重要的地位,如何确保数据读取的正确性.安全性也是我们需要研究的问题.ACID首先总结一下数据库事务正确执行的四个要素(ACID): 原子性(At ...
- (7)MySQL进阶篇SQL优化(InnoDB锁-事务隔离级别 )
1.概述 在我们在学习InnoDB锁知识点之前,我觉得有必要让大家了解它的背景知识,因为这样才能让我们更系统地学习好它.InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION ...
- [原创]java WEB学习笔记78:Hibernate学习之路---session概述,session缓存(hibernate 一级缓存),数据库的隔离级别,在 MySql 中设置隔离级别,在 Hibernate 中设置隔离级别
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- SQL Server与Oracle中的隔离级别
在SQL92标准中,事务隔离级别分为四种,分别为:Read Uncommitted.Read Committed.Read Repeatable.Serializable 其中Read Uncommi ...
- MySQL的可重复读级别能解决幻读吗
引言 之前在深入了解数据库理论的时候,了解到事物的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了.但是对于幻 ...
随机推荐
- Final,finally,finalize区别
final— 修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为 abstract的,又被声明为final的.将变量或方法声明为f ...
- python 自定义函数表达式 拟合求系数
https://docs.scipy.org/doc/scipy/reference/tutorial/integrate.html https://docs.scipy.org/doc/scipy/ ...
- Springboot 拦截器(HandlerInterceptorAdapter)中注入无效
1,传统filter和HandlerInterceptorAdapter的区别 springboot对传统Filter进行增强,添加更多细粒度的操作,分别实现预处理.后处理(调用了Service并返回 ...
- shell之lvm
#!/bin/bash #this script for LVM echo "Initial a disk..." echo -e "\033[31mWarning: ...
- 北京Uber优步司机奖励政策(3月14日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- Java:List判空的条件:List=null 和 List.size = 0
当需要对一个LIst进行判空操作时我们可使用如下两个语句: if (list == null || list.size() == 0) {} if (list != null && l ...
- LeetCode: 57. Insert Interval(Hard)
1. 原题链接 https://leetcode.com/problems/insert-interval/description/ 2. 题目要求 该题与上一题的区别在于,插入一个新的interva ...
- 生产环境 tidb部署实践
TiDB 简介 TiDB 是 PingCAP 公司受 Google Spanner / F1 论文启发而设计的开源分布式 HTAP (Hybrid Transactional and Analytic ...
- 11、Java并发编程:并发容器之CopyOnWriteArrayList
Java并发编程:并发容器之CopyOnWriteArrayList(转载) 原文链接: http://ifeve.com/java-copy-on-write/ Copy-On-Write简称COW ...
- windows安装logstash-input-jdbc并使用其导入MMSQL数据
1.安装logstash 2.修改logstash 文件夹下Gemfile文件 将source改为:https://gems.ruby-china.org 3.进入bin目录 执行logstash-p ...