众所周知,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
: » InnoDB 中 RR(Repeatable Read) 隔离级别下不存在幻读?
原创文章,作者:6024010,如若转载,请注明出处:https://blog.ytso.com/252309.html