InnoDB 中 RR(Repeatable Read) 隔离级别下不存在幻读?

SQL herman 639浏览
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:codedq,发送下载链接帮助你免费下载!
本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:codedq,之前的微信号好友位已满,备注:返现
饿了么大量招人,我内推!Java 方向!薪资不设上限,工作年龄不限!工作地点限魔都,可电话面试!简历,发我微信:codedq
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领

众所周知,MySQL 是国内使用最多的数据库,拥有众多的用户,但是各方面的相关文章,互相驳论!今天我们来说一说,InnoDB 中 RR(Repeatable Read) 隔离级别下到底存不存在幻读?

标准 SQL

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

于是,就有不少人得出结论:MySQL 的 InnoDB 中 RR(Repeatable Read) 隔离级别下存在幻读!

根据我前面的那篇,MySQL 加锁处理分析可以得知,对于 Innodb,Repeatable Read (RR) 针对当前读,RR 隔离级别保证对读取到的记录加锁 (记录锁),同时保证对读取的范围加锁,新的满足查询条件的记录不能够插入 (间隙锁),不存在幻读现象。

这个和前面标准情况下就相互驳论了,到底是怎么回事?

不少网友都有这样的疑惑!

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

这是因为 mysql innodb 引擎的实现,跟标准有所不同。

在 MySQL 5.6 的版本中,官方isolevel_repeatable-read有这样一段解释:

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 的标准是有一些差异的。

除此之外,通过 MySQL 的源码也可以看出 InnoDB 中 RR(Repeatable Read) 隔离级别下是否存在幻读问题!

实际上,正如官方所说,Innodb 的 RR 隔离界别对范围会加上 GAP,正常情况下是不会存在幻读。那如果有“例外”呢?

我们再来看看 MySQL 官网上的另一段解释:

By default, InnoDB operates in REPEATABLE READ transaction isolation level and with the innodblocksunsafeforbinlog system variable disabled. In this case, InnoDB uses next-key locks for searches and index scans, which prevents phantom rows (see Section 13.6.8.5, “Avoiding the Phantom Problem Using Next-Key Locking”).

翻译过来,大致的意思是说:当隔离级别是可重复读,且禁用 innodblocksunsafeforbinlog 的情况下,在搜索和扫描 index 的时候使用的 next-key locks 可以避免幻读。

MySQL 的 rr 级别解决了大部分幻读问题,但有几个例外。具体可以看https://dev.mysql.com/doc/refman/5.7/en/innodb-consistent-read.html

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号1:xmtxtt(5000人已满),微信号2:xttblog(5000人已满),微信号3:codedq(超3800)。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!

本文原文出处:业余草: » InnoDB 中 RR(Repeatable Read) 隔离级别下不存在幻读?