Innodb 中 RR 隔离级别可否防止幻读?

问题引出

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

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

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

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

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

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

ontheway
弱弱地问一句,我看的书里面都说的是RR隔离级别不容许脏读和不可重复读,可是能够幻读,怎么和做者说的不同呢?ui

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

求证官方文档

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

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.htm

大体意思就是,在 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,理论上不会存在幻读,可是是否有例外呢,这个还须要进一步求证。

相关文章
相关标签/搜索