併發控制是數據庫理論裏面最難的課題之一數據庫
併發控制首先了解一下事務,transaction數據結構
定義以下,併發
其實transaction關鍵是,要知足ACID屬性,分佈式
左邊的正式的定義,因爲的intuitive的理解
其中可能Consistency比較難理解一下,其餘都比較直觀,對於單機數據庫而言consistency其實不是個顯著的問題,但對於分佈式數據庫這就是個主要問題性能
那麼問題就是如何設計讓Transaction知足ACID?flex
一種簡單的方法就是,Strawman Systemui
串行執行保障consistency和isolate,整個庫的copy保障atomicity,這個方法早期用在SQLlite中,它主要是用在嵌入式場景,訪問量和數據量都很小atom
但這個方法的性能過低設計
下面就看看對ACID的各個屬性,通常是如何設計來知足的3d
原子性問題,
最經常使用的方法是Log,Undo&Redo,這樣若是事務abort,能夠根據undo日誌來回滾,達到原子性保證
還有種方法是Shadow Paging,也是MVCC,我修改的時候,把要修改的page複製一份去改,典型的使用是CouchDB
首先Consistency是邏輯的,什麼意思?
就是和實現無關,作一筆轉帳,兩邊的數據在邏輯上應該是對的,不管你底層是如何實現的,用何種數據結構
因此database consistency是指,作過的更新,在更新後,不管從什麼地方角度去看,他都應該是同樣的,好比在不一樣的transaction中,不一樣的client,不一樣的。。。
對於單機數據庫,這實際上是比較容易達成的
transaction consistency,是指應用層面的,外部的一致性,不光是數據庫內部的,這種一致性須要應用本身去保障
隔離性,每一個transaction執行的時候,不會受到其餘的transaction的干擾
由於咱們要提升數據庫的性能,因此不可能讓transaction串行執行,因此transaction必定是併發執行的,這樣必定會存在interleave的問題
由於把transaction在物理上去作隔離必定是比較低效的,因此實際的作法都是讓各個transaction interleave的執行,但其中要注意避免衝突,conflict
避免衝突通常都是要加鎖,因此天然會有悲觀和樂觀鎖的分別
這裏先不談怎麼避免衝突
咱們先看下interleave執行會帶來哪些問題?
對於這個例子,兩個transaction,一個是轉帳,一個是加利息
T1,T2,若是順序執行的結果是同樣的
這裏注意,T1,T2自己誰先執行,這個是要應用控制的,對於數據庫而言,不管誰先執行都是對的
那麼能夠看到interleave執行的結果多是good,也多是bad
若是判斷是好是壞?這個很直覺,和串行執行結果同樣就是好的,不然就是壞的
因此這裏給出一堆概念,只是就是想說明,你interleave執行的結果必定要和串行執行同樣
這樣給transaction調度帶來很大的flexible,由於只要知足serializable schedule,就能夠任意的併發調度
Serializable Schedule的定義,一個Schedule和任意一個Serial Schedule是Equivalent的,即執行結果相同
那麼咱們怎麼判斷一個sechdule是不是serializable?
咱們先看看,若是不知足serializable schedule,會發生什麼?Conflict
衝突的雙方必定是在不一樣的transaction中,而且其中至少有一個是write操做
因此Conflict分爲3種,read-read是不會衝突的
那麼如今的思路,咱們只要去看看sechdule中是否存在這些conflict,若是不存在,咱們就能夠認爲這個sechdule是serializable
形式化的表達就是,若是S是和任意一個serial schedule衝突等價的,那麼S就是conflict serializable;由於若是存在上面的衝突就不可能和serial schedule衝突等價
這裏須要注意,咱們判斷衝突的時候,通常只會看是否同時對一個object有讀寫,好比對於Unrepeatable Read,咱們不會看後面仍是不是有那個read,或者對於dirty reads,若是後面沒有abort,也不會有問題;
因此這裏是充分但沒必要要條件,不知足conflict serializable,也不必定就獲得錯誤的結果,可是知足,獲得的結果必定是正確的
下面就要找一種方法,能夠判斷S是不是conflict serializable
咱們能夠把任意不衝突的operation進行swap,看看最終能不能變成一個serial schedule
例子,
這個方法看着比較簡單,但若是transaction比較多的話,會很難操做
因此須要一個更形式化的方法,稱爲依賴圖
其實就是把衝突的依賴用線連起來,若是有環,說明是沒法conflict serializable的
好比,你看右邊的例子,是沒法conflict serializable的
而example2,是能夠conflict serializable,由於依賴圖裏面沒有環
前面講的都是Conflict Serialization
還有一種更爲寬泛的叫作,View Serialization
定義很難理解,從例子上看,就是有些不符合conflict serialization的case,算出來結果也是對的,好比例子裏面,由於是blind write,因此A的結果只會有最後一個write決定,因此這個schedule仍是能夠強行等價於一個serial schedule的
View Serialization能夠比Conflict Serialization有更多,更靈活的schedule,可是這個難於判斷,很難實現
因此整體來講,關係是這樣的,越大調度越靈活,可是機制和判斷越複雜