我理解的MVCC內部實現原理

  MySQL InnoDB存儲引擎,實現的是基於多版本的併發控制協議——MVCC (Multi-Version Concurrency Control) (注:與MVCC相對的,是基於鎖的併發控制,Lock-Based Concurrency Control)。MVCC最大的好處,相信也是耳熟能詳:讀不加鎖,讀寫不衝突。在讀多寫少的OLTP應用中,讀寫不衝突是很是重要的,極大的增長了系統的併發性能,這也是爲何現階段,幾乎全部的RDBMS,都支持了MVCC。併發

  

  對於delete操做,innodb是經過先將要刪除的那一行標記爲刪除,而不是立刻清除這一行,由於innodb實現了MVCC,這些undo段用來實現MVCC多版本機制。鎖不阻塞讀,讀也不阻塞寫,這樣大大提升了併發性。那麼在一致性讀的時候,怎麼才能找到和事務開始的那個版本呢?性能

	主鍵索引,每一個行都有一個事務ID和一個undo ID,這個undo ID指向了這行的先前版本的位置。
	非主鍵索引(輔助索引secondary index),經過先找主鍵索引再找到undo段。而對於update操做,則是先標記刪除,而後insert一個新的行,接下來若是有一致性讀,那麼查找old version的行的原理和delete操做是同樣的

  

  innoDB的行記錄格式中有6字節事務ID的和7字節的回滾指針,經過爲每一行記錄添加這兩個額外的隱藏值來實現MVCC,這兩個值一個記錄這行數據什麼時候被建立,另一個記錄這行數據什麼時候過時(或者被刪除)。可是InnoDB並不存儲這些事件發生時的實際時間,相反它只存儲這些事件發生時的系統版本號。這是一個隨着事務的建立而不斷增加的數字。每一個事務在事務開始時會記錄它本身的系統版本號。每一個查詢必須去檢查每行數據的版本號與事務的版本號是否相同。讓咱們來看看當隔離級別是REPEATABLE READ時這種策略是如何應用到特定的操做的。指針

 * SELECT:
當隔離級別是REPEATABLE READ時select操做,InnoDB必須每行數據來保證它符合兩個條件:
一、InnoDB必須找到一個行的版本,它至少要和事務的版本同樣老(也即它的版本號不大於事務的版本號)。這保證了不論是事務開始以前,或者事務建立時,或者修改了這行數據的時候,這行數據是存在的。
二、這行數據的刪除版本必須是未定義的或者比事務版本要大。這能夠保證在事務開始以前這行數據沒有被刪除。
符合這兩個條件的行可能會被看成查詢結果而返回。
* INSERT:
InnoDB爲這個新行記錄當前的系統版本號。 * DELETE:
InnoDB將當前的系統版本號設置爲這一行的刪除ID。 * UPDATE:
InnoDB會寫一個這行數據的新拷貝,這個拷貝的版本爲當前的系統版本號。它同時也會將這個版本號寫到舊行的刪除版本里。 這種額外的記錄所帶來的結果就是對於大多數查詢來講根本就不須要得到一個鎖。他們只是簡單地以最快的速度來讀取數據,確保只選擇符合條件的行。這個方案的缺點在於存儲引擎必須爲每一行存儲更多的數據,
作更多的檢查工做,處理更多的善後操做。 MVCC只工做在REPEATABLE READ和READ COMMITED隔離級別下。READ UNCOMMITED不是MVCC兼容的,由於查詢不能找到適合他們事務版本的行版本;它們每次都只能讀到最新的版本。
SERIABLABLE也不與MVCC兼容,由於讀操做會鎖定他們返回的每一行數據。

  

併發控制技術:blog

LBCC:Lock-Based Concurrency Control,基於鎖的併發控制。
MVCC:Multi-Version Concurrency Control,基於多版本的併發控制協議。純粹基於鎖的併發機制併發量低,MVCC是在基於鎖的併發控制上的改進,主要是在讀操做上提升了併發量。
在MVCC併發控制中,讀操做能夠分紅兩類:
1)快照讀 (snapshot read):讀取的是記錄的可見版本 (有多是歷史版本),不用加鎖(共享讀鎖s鎖也不加,因此不會阻塞其餘事務的寫)。
2)當前讀 (current read):讀取的是記錄的最新版本,而且,當前讀返回的記錄,都會加上鎖,保證其餘事務不會再併發修改這條記錄。
相關文章
相關標籤/搜索