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,理論上不會存在幻讀,可是是否有例外呢,這個還須要進一步求證。

相關文章
相關標籤/搜索