2016-07-29 34 views
2

enter image description here這個innodb差距鎖定錯誤?

TRX1 SELECT * FROM表,其中REFID = 4更新

TRX2 插入到表(REFID)值(2);塊

trx2將被封鎖,我知道trx1將保持它的差距鎖定,[1,4),[4,7);

我的問題是爲什麼保持差距鎖定? 「insert val 2」不衝突「select refId = 4 for update」,爲什麼innodb會保持間隙鎖定,爲什麼不使用記錄鎖定?

這個問題一直困擾着我很長一段時間,請科技上帝救我。

回答

1

有趣的問題。

需要使用間隙鎖來避免phantom rows。 默認情況下,MySQL工作在REPEATABLE-READ隔離級別。如果您在交易中多次運行select ... for update,則應始終返回相同的結果。 假設您沒有間隙鎖定,並且trx2插入了refId = 4的另一行(索引不唯一)。 然後按照TRX1選擇將返回兩行:

MariaDB [test]> select * from t1 where refId=4 for update; 
+----+------+ 
| id | refId| 
+----+------+ 
| 2 | 4 | 
| 4 | 4 | 
+----+------+ 
2 rows in set (0.00 sec) 

這是不一樣的結果作爲第一選擇。

+0

yes,沒錯,虛幻行,跟隨你的測試,插入refId = 4的另一行,只要trx1保持行記錄鎖定(或沒有間隙鎖定),你可以阻塞插入refId = 4,並且虛幻幻影行;我的問題爲什麼保持差距鎖定插入refId = 1,2,3,5,6,不僅僅是4.感覺這是mysql的bug? –

+0

我認爲這個sql的gap-lock工作「select * from refId <10 for update」,gap-lock將阻止插入refId = 1,2,3,4,5,6,7到void虛線行;它應該工作範圍搜索條件,而不是等於條件。 –

+0

感謝您的回答。 –