幻讀問(wèn)題是指在讀取某條記錄時(shí),該記錄被其他事務(wù)修改,導(dǎo)致當(dāng)前事務(wù)獲取的結(jié)果與預(yù)期不符。Mysql使用多版本并發(fā)控制(MVCC)技術(shù)處理幻讀問(wèn)題。
什么是MVCC?
MVCC是基于版本的控制,可以在保證事務(wù)隔離的前提下,提高并發(fā)性。Mysql執(zhí)行一個(gè)查詢時(shí),會(huì)將當(dāng)前查詢所在時(shí)間之前,所有已提交事務(wù)所對(duì)應(yīng)的數(shù)據(jù)版本保存下來(lái)。在查詢中,Mysql只會(huì)讀取數(shù)據(jù)版本號(hào)小于或等于當(dāng)前事務(wù)版本號(hào)的數(shù)據(jù)。
SELECT * FROM table_name WHERE id=1;
這條查詢語(yǔ)句會(huì)獲取id為1的數(shù)據(jù),并記錄查詢事務(wù)的版本號(hào)為t1。如果此時(shí)其他事務(wù)修改了id為1的數(shù)據(jù)并提交,那么當(dāng)前事務(wù)仍然會(huì)讀取到版本號(hào)小于等于t1的的數(shù)據(jù)。
MVCC如何處理幻讀?
MVCC只能處理修改與查詢操作,因?yàn)樗鼰o(wú)法解決插入操作的幻讀問(wèn)題,必須使用“間隙鎖”(gap lock)來(lái)解決。
在默認(rèn)隔離級(jí)別下(REPEATABLE READ),Mysql查詢時(shí)會(huì)對(duì)符合條件范圍的記錄進(jìn)行加鎖,稱為區(qū)間鎖。如果一個(gè)事務(wù)執(zhí)行以下語(yǔ)句:
START TRANSACTION;
SELECT * FROM table_name WHERE age>20 AND age<30 FOR UPDATE;
這條查詢語(yǔ)句會(huì)對(duì)age在20到30之間的所有記錄加區(qū)間鎖,即使此時(shí)其他事務(wù)插入滿足該條件的記錄,也會(huì)被阻塞。
總結(jié)
MVCC技術(shù)能夠解決讀取操作的幻讀問(wèn)題,但是不能解決插入操作的幻讀問(wèn)題,必須使用間隙鎖。