對於 MySQL Repeatable Read Isolation 常見的三個誤解

Chester Chu
14 min readJun 21, 2019

如果對 Isolation Levels 記憶模糊可以參考這一篇:

複習資料庫的 Isolation Level 與圖解五個常見的 Race Conditions

一開始我們先看一個例子。有兩個 Transaction 同時操作 gamer 這個表格,其中一個 select 所有的資料,另一個則在中間新增了一個新的玩家,Frank,然後 commit。在 MySQL InnoDB Engine 的環境下,使用 Repeatable Read Isolation (RR Isolation) 時,資料庫的行為如下圖:

Phantom Read don’t occur

從上圖可以看到,在 Transaction B 新增了一筆資料之後,Transaction A 還是只讀取到 5 筆資料,沒有玩家 Frank 的資料,Phantom 現象並沒有發生。所以大家可能會問,MySQL InnoDB Engine 的 RR Isolation 是不是 Phantom Safe 的呢?網路上的確也有不少文章是這麼認為的。

但是讓我們繼續這個例子。Transaction A 的任務是在每週的最後一天為當下分數最高的前三名玩家增加 credit,前三名玩家的 credit 都各增加 1 分。依照上圖可以知道現在前三名的玩家分別是 Alice、Carol 跟 Bob,三個玩家的分數都達到了 740 分以上,所以可以很簡單的使用 Atomic Update (credit = credit + 1),為所有分數達到 740 分以上的玩家 credit 加 1。

雖然目前資料庫實際上有 6 筆玩家的資料,但是從 Transaction A 的視角只有看到總共 5 筆玩家的資料。在這樣的情況下,Transaction A 所做的更新是不是理論上只會影響到這 5 筆資料呢?實際的實驗結果如下圖:

Phantom caused Write Skew

從上圖中可以看到,在 Transaction A 執行更新指令後,如果馬上再重新讀取一次 gamer 表格,玩家 Frank 的資料竟然意外的出現在列表中,發生了 Phantom 現象。不僅如此,照原本的邏輯 Transaction A 應該只會為前 3 名的玩家增加 credit,但是因為 Frank 的分數也同樣高於 740 分,同樣也被增加了 credit。最後被增加 credit 的玩家總共有 4 個 ,比原本系統預計送出的 credit 還多。這種現象屬於 Write Skew,在這個例子中是因為 Phamtom 而導致的 Write Skew。

--

--

Chester Chu

A Software Engineer, Gopher and Full Stack Developer.