MySQL是一個廣泛使用的關(guān)系型數(shù)據(jù)庫管理系統(tǒng),支持事務(wù)處理,數(shù)據(jù)安全性能好。但是,在高并發(fā)、大量數(shù)據(jù)處理的環(huán)境下,MySQL容易出現(xiàn)數(shù)據(jù)不一致的問題,尤其是不可重復(fù)讀和幻讀這兩個問題更是經(jīng)常出現(xiàn)。
不可重復(fù)讀是指在同一事務(wù)中,讀取同一記錄兩次的結(jié)果不同,這是因為在使用該記錄的過程中,在兩次讀取之間有別的事務(wù)進行了更新操作,導(dǎo)致兩次讀取的結(jié)果不一致。該問題常常出現(xiàn)在更新鎖定行的情況下。
START TRANSACTION; SELECT * FROM user WHERE id=1 FOR UPDATE; ...(其他操作中包含更新user表的操作) SELECT * FROM user WHERE id=1; COMMIT;
上述操作中,事務(wù)首先讀取id為1的記錄并對其進行更新,期間另一事務(wù)更新了同一條記錄,當(dāng)首先的事務(wù)再次讀取該記錄時,發(fā)現(xiàn)數(shù)據(jù)已被更改,導(dǎo)致不可重復(fù)讀的問題。
幻讀是指在同一事務(wù)中,讀取同一范圍的記錄兩次的結(jié)果不同,尤其是在插入、刪除和更新操作的情況下,如果多個事務(wù)讀取同一個表中的不同數(shù)據(jù),同時插入或刪除記錄,就可能發(fā)生幻讀。幻讀問題不同于不可重復(fù)讀,因為它涉及多行數(shù)據(jù)的讀取。
START TRANSACTION; SELECT * FROM user WHERE age >20; ...(其他操作中包含了一次插入age>20的記錄) SELECT * FROM user WHERE age >20; COMMIT;
上述操作中,事務(wù)在讀取age大于20的記錄范圍后,在其他操作中插入了一條符合范圍的記錄,在數(shù)據(jù)提交前再次讀取范圍內(nèi)的記錄時,發(fā)現(xiàn)數(shù)據(jù)增加了一行,導(dǎo)致幻讀問題。
總而言之,在編寫程序時應(yīng)避免并發(fā)訪問,要使用合理的鎖機制,事務(wù)的隔離級別也應(yīng)根據(jù)需要選擇。