MySQL的innodb引擎是如何實現MVCC的。innodb會爲每一行添加兩個字段,分別表示該行建立的版本和刪除的版本,填入的是事務的版本號,這個版本號隨着事務的建立不斷遞增。在repeated read的隔離級別(事務的隔離級別請看這篇文章)下,具體各類數據庫操做的實現:mysql
select:知足如下兩個條件innodb會返回該行數據:(1)該行的建立版本號小於等於當前版本號,用於保證在select操做以前全部的操做已經執行落地。(2)該行的刪除版本號大於當前版本或者爲空。刪除版本號大於當前版本意味着有一個併發事務將該行刪除了。sql
即 能夠查到的知足的條件 :該行的建立的版本號=<當前事務的版本號<該行的刪除版本號數據庫
insert:將新插入的行的建立版本號設置爲當前系統的版本號。併發
delete:將要刪除的行的刪除版本號設置爲當前系統的版本號。mvc
update:不執行原地update,而是轉換成insert + delete。將舊行的刪除版本號設置爲當前版本號,並將新行insert同時設置建立版本號爲當前版本號。性能
其中,寫操做(insert、delete和update)執行時,須要將系統版本號遞增。大數據
因爲舊數據並不真正的刪除,因此必須對這些數據進行清理,innodb會開啓一個後臺線程執行清理工做,具體的規則是將刪除版本號小於當前系統版本的行刪除,這個過程叫作purge。.net
經過MVCC很好的實現了事務的隔離性,能夠達到repeated read級別,要實現serializable還必須加鎖。線程
參考:blog
多版本併發控制技術已經被普遍運用於各大數據庫系統中,如Oracle,MS SQL Server 2005+, Postgresql, Firebird, Maria等等,開源數據庫MYSQL中流行的INNODB引擎也採用了相似的併發控制技術.本文就將結合實例來解析不一樣事務隔離等級下INNODB的MVCC實現原理.
1 MVCC概述
1.1 MVCC簡介
MVCC (Multiversion Concurrency Control),即多版本併發控制技術,它使得大部分支持行鎖的事務引擎,再也不單純的使用行鎖來進行數據庫的併發控制,取而代之的是,把數據庫的行鎖與行的多個版本結合起來,只須要很小的開銷,就能夠實現非鎖定讀,從而大大提升數據庫系統的併發性能. 1.2 實現原理 MVCC能夠提供基於某個時間點的快照,使得對於事務看來,老是能夠提供與事務開始時刻相一致的數據,而無論這個事務執行的時間有多長.因此在不一樣的事務看來,同一時刻看到的相同行的數據多是不同的,即一個行可能有多個版本.是否聽起來難以想象呢? 原來,爲了實現mvcc, innodb對每一行都加上了兩個隱含的列,其中一列存儲行被更新的」時間」,另一列存儲行被刪除的」時間」. 可是innodb存儲的並非絕對的時間,而是與時間對應的數據庫系統的版本號,每當一個事務開始的時候,innodb都會給這個事務分配一個遞增的版本號,因此版本號也能夠被認爲是事務號.對於每個」查詢」語句,innodb都會把這個查詢語句的版本號同這個查詢語句遇到的行的版本號進行對比,而後結合不一樣的事務隔離等級,來決定是否返回該行.
下面分別以select、delete、 insert、 update語句來講明: 1) SELECT 對於select語句,只有同時知足了下面兩個條件的行,才能被返回: •行的被修改版本號小於或者等於該事務號 •行的被刪除版本號要麼沒有被定義,要麼大於事務的版本號:行的刪除版本號若是沒有被定義,說明該行沒有被刪除過;若是刪除版本號大於當前事務的事務號,說明該行是被該事務後面啓動的事務刪除的,因爲是repeatable read隔離等級,後開始的事務對數據的影響不該該被先開始的事務看見,因此該行應該被返回. 2) INSERT 對新插入的行,行的更新版本被修改成該事務的事務號 3) DELETE 對於刪除,innodb直接把該行的被刪除版本號設置爲當前的事務號,至關於標記爲刪除,而不是實際刪除 4) UPDATE 在更新行的時候,innodb會把原來的行復制一份到回滾段中,並把當前的事務號做爲該行的更新版本
1.3 MVCC的優缺點 上述策略的結果就是,在讀取數據的時候,innodb幾乎不用得到任何鎖, 每一個查詢都經過版本檢查,只得到本身須要的數據版本,從而大大提升了系統的併發度. 這種策略的缺點是,爲了實現多版本,innodb必須對每行增長相應的字段來存儲版本信息,同時須要維護每一行的版本信息,並且在檢索行的時候,須要進行版本的比較,於是下降了查詢的效率;innodb還必須按期清理再也不須要的行版本,及時回收空間,這也增長了一些開銷 2 INNODB支持的事務隔離等級 INNODB支持並實現了ISO標準的4個事務隔離等級,即 READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE. 1) READ UNCOMMITTED (能夠讀未提交的): 查詢能夠讀取到其餘事務正在修改的數據,即便其餘事務的修改尚未提交.這種隔離等級沒法避免髒讀. 2) READ COMMITTED(只能夠讀已經提交的):其餘事務對數據庫的修改,只要已經提交,其修改的結果就是可見的,與這兩個事務開始的前後順序無關.這種隔離等級避免了髒讀,可是沒法實現可重複讀,甚至有可能產生幻讀. 3) REPEATABLE READ(可重複讀):比read committed更進了一步,它只能讀取在它開始以前已經提交的事務對數據庫的修改,在它開始之後,全部其餘事務對數據庫的修改對它來講均不可見.從而實現了可重複讀,可是仍有可能幻讀 4) SERIALIZABLE(可串行化):這是事務隔離等級的最高級別.其實現原理就是對於全部的query,即便是查詢,也會加上讀鎖,避免其餘事務對數據的修改.因此它成功的避免了幻讀.可是代價是,數據庫系統的併發處理能力大大下降,因此它不會被用到生產系統中. 咱們對MVCC和標準事務隔離等級有所瞭解之後,再結合實例來看看其具體表現吧.