天天看點

MVCC(H2、Inoodb,CopyOnWrite, Clojure)

之前,研究H2源碼的時候,重點了解了一下MvStore。結合它的文檔和Inoodb的實作,發現它叫MVCC(Multi-Version Concurrency Control),即多版本控制,同時它也叫樂觀鎖。後面發現它的理念在Java的CopyOnWriteList,Clojure的辨別與狀态分離,驚奇地發現它似乎無處不在,于是,試着對此進行總結。

相對這些名詞“樂觀鎖”比較合其神,所謂樂觀,與“悲觀鎖”對應。它們都是針對并發問題提出的。試想如果小D有一份檔案,同時有任意個人同時去讀它是沒有問題的。他們可以圍着一起看。但是要同時寫呢?那就隻能一個一個來寫,于是就有了鎖。普通的鎖也叫“悲觀鎖”,大意是當需要去寫這個檔案時,其他人隻能候着,也就是連看都不能看。這很讨厭,其他的人可能隻想同時瞅一眼,但要采取這種政策隻能候着。那能不能改呢?小D想了一種方法,就是給一份大家看,給另一份供人寫,寫的人也隻能一個一個寫,但是大家同時是可以看了。當有人去寫好時,就把這份檔案複制一份替換原來那份給人看的檔案。這就是所謂的CopyOnWrite,也就是寫了之後就複制。Java的CopyOnWriteList就是這樣的思想。那麼是不是還可以改進,可以更樂觀點呢,于是小D想,幹脆誰想用每人列印一份算了。這樣你寫自己在自己檔案上寫,這樣每個檔案就是一個版本,出現了多個版本,但這時又有問題了,檔案隻允許一個版本是有效的,于是,小D想了個辦法,設定了一個東西叫版本号。開始是0,大家列印的都是0。有人修改之後,送出成功就變成了1。好多人同時修改,一擁而上。總有人是先修改的,于是那個人就送出成功了,剩下的人驚奇的發現他們的版本小于現有版本,資料廢棄,于是隻能把新版資料拿回去重改。這樣有了多個版本,這種政策就是MVCC。因為它對資料是樂觀的,大家都可以同時改嘛,最後一緻就可以了。是以也叫樂觀鎖。

這種樂觀如果遇上“讀多于寫”,這是非常合适的。但如果“寫”比較多,那可能出現不斷有事務重複執行。資料庫的很多應用中讀都是遠多于寫。H2的MvStore,MySQL的InnoDB都實作了這種政策。而作為支援并發良好的Clojure,為了實作并發的控制,實作了Ref變量,也使用類似的政策,實作了除了D之外所有資料庫ACI特性。各種MVCC的實作是不同的,下一步需要繼續研究細節和應用。