在上文《分佈式事務?咱先弄明白本地事務再說 - ACID》中,咱們講解了數據庫的事務及事務的特性ACID,瞭解到一個數據庫要支持事務,就須要實現完備的事務的規範,咱們才能說這是一個支持事務的數據庫,例如Mysql、Oracle等。
本文就來討論一下數據庫實現事務的幾個關鍵階段,背後都經歷了哪些曲折的技術變遷。html
數據庫的事務,本質上是解決數據庫併發的問題,處理多個數據操做時相互不干擾,都能獲得正確的執行結果,這個問題在應用層是沒法解決的,由於你徹底不知道同時可能有另外一個程序(進程)也在操做相同的數據項,因此,這個問題必須由數據庫來解決。sql
最簡單的思路,就是徹底順序執行全部的數據庫操做,不須要加鎖,簡單的說就是全局排隊,序列化進行全部的事務單元,數據庫同時只處理一個事務,特色是強一致性,處理性能低。
這種模式適應於早期的C/S開發模式,單機系統,一個系統,一個數據庫(例如Access數據庫),徹底本地用戶+本地系統+本地事務。數據庫
開始支持並行處理事務,若是事務之間涉及到相同的數據項時,會使用排他鎖,或叫互斥鎖,先進入的事務獨佔數據項之後,其餘事務被阻塞,等待前面的事務釋放鎖。併發
注意,在整個事務1結束以前,鎖是不會被釋放的,因此,事務2必須等到事務1結束以後開始。分佈式
採用了 並行+排他鎖
之後,大幅提高了數據庫事務處理效率,若是幾個事務之間沒有共享數據項,徹底能夠並行被處理,但,一些數據庫大牛們顯然對這個性能還不知足,進一步研究細化發現,全部的事務當中,對數據的操做無非是讀和寫排列組合的幾種結果, 讀讀、寫寫、讀寫、寫讀
這4種狀況的不斷重複。性能
哪些操做之間能夠相互兼容,或者共享呢?例如,讀的時候爲何要阻止讀呢?優化
因此,讀寫鎖就應用而生了,進一步細化鎖的顆粒度,區分讀和寫,讓讀和讀之間不加鎖,這樣下面的倆個事務就能夠同時被執行了。版本控制
讀寫鎖,可讓讀和讀並行,而讀和寫、寫和讀、寫和寫這幾種之間仍是要加排他鎖。code
有人可能要說,優化到這個份上,已經差很少了吧,還有空間?
大牛們用行動告訴世人,答案是確定的。
每每,肯定一個模型不是最難的,難的是對這個模型實現的境界,大牛們會把本身的實現往死裏優化,並行+讀寫鎖
解決了讀和讀的並行,大牛們接下來要解決的是寫和讀、讀和寫,甚至寫和寫是否均可以並行!htm
這個技術就是如今大部分數據庫在使用的事務處理技術,MVCC(Multi Version Concurrency Control),也就是Copy on Write的思想,對數據項進行多版本控制,一個精妙的想法,用空間換時間,進一步優化鎖,減小鎖。
給每條記錄增長版本號和刪除倆個字段,在事務開始的時候copy一個新的版本,此時事務操做的其實是一個副本,所以不會影響其餘事務對此數據項的讀操做,選擇版本號最大的記錄讀取。
另外,MVCC支持讀已提交 和 重複讀
倆種隔離級別,串行和讀未提交都沒有意義,一個必需要求排隊執行,另外一個要求必須讀取最新數據。
人類對速度的激情是沒有最快,只有更快。
因此,以上方案的演變,本質是速度上的逐步提高的過程,到目前MVCC爲止,在數據庫層面能作的事情已經很少了。
進一步,如何解決寫和寫衝突的問題,這裏提供倆個思路