MySQL的大多數(shù)事務(wù)型存儲(chǔ)引擎都不是簡(jiǎn)單的行級(jí)鎖。各大數(shù)據(jù)庫(kù)基本都采用MVCC,但不盡相同。
InnoDB的簡(jiǎn)化版:(MVCC實(shí)現(xiàn)原理)
在每行記錄后面保存兩個(gè)隱藏的列來(lái)實(shí)現(xiàn),一個(gè)保存了行的創(chuàng)建版本號(hào),一個(gè)保存行的過(guò)期版本號(hào)(刪除版本號(hào))。
版本號(hào):
- 系統(tǒng)版本號(hào):每開(kāi)始一個(gè)新的事務(wù),系統(tǒng)版本號(hào)就會(huì)自動(dòng)增加
- 事務(wù)版本號(hào):事務(wù)開(kāi)始時(shí)刻的系統(tǒng)版本號(hào)
當(dāng)執(zhí)行select操作時(shí)候:
- 只查找版本早于當(dāng)前事務(wù)版本的數(shù)據(jù)行。 確保事務(wù)讀取的行,在事務(wù)開(kāi)始之前就存在的,或者是事務(wù)自身插入或者修改過(guò)的。
- 行的刪除版本號(hào)要么未定義,要么大于當(dāng)前事務(wù)版本號(hào)。 確保事務(wù)查詢(xún)到的行,在事務(wù)開(kāi)始之前沒(méi)被刪除。
insert操作:
為新插入的每一行保存當(dāng)前系統(tǒng)版本號(hào)為行創(chuàng)建版本號(hào)。
delete操作:
為刪除的行保存當(dāng)前系統(tǒng)版本號(hào)作為行刪除版本號(hào)。
update操作:
為插入一行新數(shù)據(jù)保存當(dāng)前版本號(hào)作為該新行行創(chuàng)建版本號(hào),同時(shí)保存當(dāng)前系統(tǒng)版本號(hào)到原來(lái)的行作為行刪除版本號(hào)。
可見(jiàn)update = delete+insert
采用MVCC這個(gè)原理,大多操作可以不用加鎖,使得讀數(shù)據(jù)操作簡(jiǎn)單,性能好,缺點(diǎn)是額外的存儲(chǔ)空間消耗,更多的行檢查和維護(hù)工作。MVCC只能在REPEATABLE READ 和READ COMMITTED兩個(gè)隔離級(jí)別下工作。其他兩個(gè)隔離級(jí)別跟MVCC不兼容。