Phantom Problem(幻讀)問題

半張飯卡-半個程式設計師發表於2020-12-09

Phantom Problem是指同一事務下,連續執行兩次同樣的SQL語句可能導致不同的結果,第二次的SQL語句可能會返回之前不存在的行。在預設的事務隔離級別下,即REPEATABLE READ下,InnoDB儲存引擎採用Next-Key Locking機制來避免Phantom Problem(幻讀問題)。

舉個例子:

建立測試表t:

CREATE TABLE t (a INT PRIMARY KEY);
INSERT INTO t SELECT 1;
INSERT INTO t SELECT 2;
INSERT INTO t SELECT 5;

(事務隔離級別:READ COMMITED)事務T1先執行如下程式碼:

SELECT * FROM t WHERE a>2 FOR UPDATE;

這是事務T1並沒有進行commit操作;應該返回a=5這個結果;假如與此同時,另一個事務T2插入了4這個值,並且資料庫允許該操作,那麼事務T1再次執行上述SQL語句會得到結果4和5。這與第一次得到的結果不同,違反了事務的隔離性,即當前事務能夠看到其他事務的結果。其過程如下:
在這裡插入圖片描述

InnoDB儲存引擎採用Next-Key Locking的演算法來避免Phantom Problem。對於上述的SQL語句SELECT * FROM t WHERE a>2 FOR UPDATE,其鎖住的不是5這個單值,而是對(2,+ ∞ )這個單位加了X鎖(排它鎖)。因此任何對於這個範圍的插入都是不允許的。從而避免了Phantom Problem。

InnoDB儲存引擎預設的事務隔離級別是REPEATABLE READ,採用Next-Key Locking(鎖定一個範圍,並且鎖定記錄本身)的方式加鎖。而在事務隔離級別READ-COMMITED下,僅採用Record Lock(單個行記錄上的鎖),因此在上述栗子中,會話A需要將事務的隔離級別設定為READ-COMMITED。

相關文章