多版本并發(fā)控制(MVCC)
MVCC可以理解成為行級鎖的一個變種,但是它在很多情況下避免了加鎖操作,因此開銷更低超凳。
雖然實現(xiàn)機制有所不同钞澳,但大都實現(xiàn)了非阻塞的讀操作怠惶,寫操作也只鎖定必要的行。
MVCC實現(xiàn)
MVCC的實現(xiàn)是通過保存數(shù)據(jù)在某個時間點的快照來實現(xiàn)的轧粟,也就是說策治,不管需要執(zhí)行多長時間,每個事務(wù)看到的數(shù)據(jù)都是一致的兰吟。根據(jù)事務(wù)開始的時間不同通惫,每個事務(wù)對同一張表,同一時刻看到的數(shù)據(jù)可能是不一樣的混蔼。
innoDB的MVCC履腋,是通過在每行記錄后面保存兩個隱藏起來的列實現(xiàn)的。這兩個列惭嚣,一個保存了行的創(chuàng)建時間府树,一個保存行的過期時間(或刪除時間)。當然料按,存儲的并不是實際的是兼職奄侠,而是系統(tǒng)的版本號(system version number)。每開始一個新事務(wù)载矿,系統(tǒng)版本號都會自動遞增垄潮。每開啟一個新的事務(wù),系統(tǒng)版本號都會遞增闷盔。事務(wù)開始時刻的系統(tǒng)版本號會做為事務(wù)的版本號弯洗。用來和查詢到的每行記錄的版本號進行比較。
下邊看下可重復(fù)讀(REPEATABLE READ)隔離級別下逢勾,MVCC是如何具體操作的牡整。
SELECT :
innoDB會根據(jù)以下兩個條件檢查每條記錄:
1,innoDB只查找版本早于當前事務(wù)版本的數(shù)據(jù)行(也就是說溺拱,行的系統(tǒng)版本號小于或等于事務(wù)的系統(tǒng)版本號)逃贝,這樣可以確保事務(wù)讀取到的行谣辞,要么是在事務(wù)開始前已經(jīng)存在的,要么是事務(wù)自身插入或者修改過的沐扳。
2泥从,行的刪除版本要不未定義,要么大于當前事務(wù)版本號沪摄。這樣可以保證事務(wù)讀取到的行躯嫉,在事務(wù)開始前未本刪除。
只有符合上述兩個條件的記錄杨拐,才能返回作為查詢結(jié)果祈餐。INSERT :
innoDB為新插入的每一行保存一個當前系統(tǒng)版本號作為行版本號。DELETE:
innoDB為刪除的每一行保存一個當前系統(tǒng)版本號作為行刪除標識哄陶。UPDATE:
innoDB為插入一行新紀錄帆阳,保存當前系統(tǒng)版本號作為行版本號,同時保存當前系統(tǒng)版本號到原來的行作為行刪除標識奕筐。
保存這兩個額外的系統(tǒng)版本號,使大多數(shù)讀操作都可以不用加鎖变骡,這樣設(shè)計使得讀操作很簡單离赫,性能很好,并且也能保證只會讀取到符合標準的行塌碌。不足之處是每行記錄都需要額外的存儲空間渊胸,需要做更多的檢查工作,以及一些額外的維護工作台妆。
注:MVCC只在 提交讀(READ COMMITTED)和可重復(fù)讀(REPEATABLE READ)工作翎猛。因為未提交讀總是讀取最新的行,可串行化則會對所有的讀取的行都加鎖接剩。