InnoDB如何解決臟讀、不可重復(fù)讀和幻讀的?
在InnoDB中,采用MVCC解決了臟讀和不可重復(fù)讀的問題,而結(jié)合MVCC和間隙鎖則解決了幻讀。
臟讀的解決
臟讀是指一個事務(wù)可以讀取另一個事務(wù)未提交的數(shù)據(jù),造成數(shù)據(jù)不一致。在讀已提交(Read Committed)隔離級別下,事務(wù)只能讀取到其他事務(wù)已經(jīng)提交的數(shù)據(jù)版本。因此,如果一個事務(wù)在讀取數(shù)據(jù)時,另一個事務(wù)已經(jīng)修改了這些數(shù)據(jù)但尚未提交,那么讀取事務(wù)將不會看到這些未提交的更改。
在執(zhí)行讀操作時,當(dāng)事務(wù)處于“讀已提交”隔離級別下,InnoDB會獲取當(dāng)前最新的全局事務(wù)ID,代表當(dāng)前時刻所有已提交事務(wù)的最新狀態(tài)。InnoDB會檢查每個數(shù)據(jù)行的版本,如果該版本由一個小于或等于當(dāng)前事務(wù)ID的事務(wù)修改,并且該事務(wù)已提交,則這個版本是可見的。這確保了事務(wù)只能看到在其開始之前已經(jīng)提交的數(shù)據(jù)版本。
不可重復(fù)讀的解決
不可重復(fù)讀指一個事務(wù)讀取同一行數(shù)據(jù)兩次,但在兩次讀取之間另一個事務(wù)修改了該行數(shù)據(jù),導(dǎo)致兩次讀取結(jié)果不同。InnoDB通過MVCC來解決不可重復(fù)讀的問題。在Repeatable Read(重復(fù)讀)隔離級別下,采用快照讀進行數(shù)據(jù)讀取時,僅在第一次讀取時生成一個Read View,后續(xù)的所有快照讀都使用相同快照,因此不會發(fā)生不可重復(fù)讀的問題。
幻讀的解決
對于幻讀問題,在InnoDB的Repeatable Read(重復(fù)讀)隔離級別中,基于MVCC和間隙鎖在一定程度上可以避免幻讀,但無法完全避免。當(dāng)一個事務(wù)執(zhí)行當(dāng)前讀時,可能會導(dǎo)致幻讀的發(fā)生。