CMU Database Systems - Timestamp Ordering Concurrency Control

2PL是悲觀鎖,Pessimistic,這章講樂觀鎖,Optimistic,單機的,非分佈式的算法

Timestamp Ordering,以時間爲序,這個是很是天然的想法,按每一個transaction的時間來排誰先執行數據庫

這裏會有幾個問題,Timestamp是什麼,由誰來打,何時打上Timestamp緩存

首先每一個T須要有一個unique的timestamp,這個在單機很容易實現;
其次,Timestamp必須是單調遞增的
最後,不一樣的schema會選擇在不一樣的時間給txn打上timestamp,多是txn剛到的時候,也多是txn執行完的時候安全

Timestamp能夠有多種形式,系統時間,邏輯counter,或者hybrid併發

 

Basic Timestamp Ordering Protocol分佈式

設計比較直覺,性能

首先,給每一個object加上,讀時間戳,寫時間戳,表示最後一次讀寫該對象的時間優化

讀的時候,拿當前事務ts和寫ts比較,若是寫ts比較新,那麼讀須要abort,由於,你不能讀一個將來的值;
寫的時候,要同時比較該對象的讀,寫ts,比較寫是由於你不能用過去的值覆蓋將來的值,比較讀,是由於若是有將來的txn讀過這個值,你就不能再更新spa

同時,這裏不管讀寫,都會把當前的value,copy到local進行緩存,這是避免txn頻繁衝突,由於對於一個txn數據應該能夠重複讀的,因此若是不緩存,那麼若是這個值被別的txn改了,會很容易致使txn abort設計

例子,

T1在更新A的時候,ts已經小於W-TS,因此不能更新,須要abort

 

Thomas write rule,一種下降abort機率的方法

思路若是txn在write的時候發現,W-TS大,即將來的時間,那麼直接跳過這個write,由於這個write反正都是被覆蓋的,因此不關鍵;

 

用Basic T/O產生的shedule是不可recoverable的

什麼叫recoverable,當你commit的時候,你所依賴的全部txn已經完成commit;
這樣纔是可恢復的,否則你commit完後,數據庫crash了,那麼你以前看到的或依賴的txn尚未commit就丟失了,但你的結果已經完成commit,就產生不一致

Basic T/O的問題,

1. 不可recoverable
2. overhead比較重,須要每次讀寫都更新ts,並且還須要把數據copy到local
3. 長txn會starve,比較難成功,由於很容易被衝突,abort

 

樂觀鎖,基於的假設,衝突極少發生,不然樂觀鎖的成本反而更加高

因此基於這樣的假設,那麼算法能夠進一步優化,OCC算法

分3個階段,

1. 每一個txn都建立一個獨立的workspace,不管讀寫,都把數據copy到本身的workspace裏面進行操做

2. validate,這個txn是否和其餘txn衝突

3. 若是不衝突,把變動合併到global數據庫

能夠看到,其中比較難的是第二步,validation

validation就是判斷當前txn和全部其餘的txn是否有WR或WW衝突

首先假設同時只有一個txn進行validation,即serial validation

而後txn的ts是在validation階段的開始被assign的,這個很關鍵

如何check當前txn和其餘全部的txn之間是否有衝突?

若是Ti 先於 Tj,那麼咱們要知足如下3個條件中的一個

1. Ti在Tj開始以前,完成全部3個階段,就是串行執行,這個確定沒有衝突

 

2. Ti在Tj開始Write phase前完成,而且Ti沒有寫任何會被Tj讀到的對象

例子,

T1寫了A,而在T2中會讀到A,這樣就不知足上面的條件2

 這種狀況是安全的,由於這個時候T2也已經結束了,而且T2只是讀了A當並無寫任何數據

 

3. Ti的Read phase比Tj的Read phase早結束,而且Ti沒有寫任何會被Tj讀或寫到的對象

例子,

這個例子T1在validation的時候,T2沒有讀或寫A,因此安全的,把T1的結果提交到Database

而後這個時候T2讀A,是不會有問題的

OCC算法的性能問題,

也要把數據copy到本地,比較高的overhead
Validation和Write會成爲瓶頸,由於這裏須要串行
Abort的代價更高,由於這裏txn已經作完了,纔會validation判斷是否要abort

OCC算法,還有明顯的性能問題,當txn不少的時候,每一個txn提交,都須要去判斷是否和其餘的txn衝突,就算沒有衝突,可是每次比較的代價也是很是高的

因此提出Partition-based T/O,若是數據水平劃分紅不少partition,那麼在每一個partition上的txn就會變少,比較txn之間的衝突的效率就會提高

Partitioned T/O的性能問題是,

若是每一個txn都只訪問一個partition,那麼性能會比較好

 

幻讀

以前的txn都是讀寫,可是沒有insert或delete

因此對於下面的狀況,2PL是無論用的,由於鎖機制只能鎖已經存在的tuple,因此這個問題是Phantom,幻讀

 

解決這個問題的方法,

predict locking,知足這個predict的records都lock,這個很難實現

 對於predict locking一種可能的實現方式是,index locking,鎖包含這個predict的index page

若是沒有合適的index,只能鎖表上的每一頁或直接鎖table 

 經過重複查詢來判斷是否有幻讀,很低效的方式,通常數據庫都不會採用

 

這裏最後再講一個概念,隔離級別

最強的就是以前一直在講的,serializable,雖然有最強的一致性,但也大大犧牲了數據庫的併發性

可是有的應用和場景,其實不須要那麼強的一致性,因此能夠犧牲一些一致性來換取必定的併發性

不一樣的隔離級別會產生哪些不一致狀況在右圖能夠看出

那麼如何實現這些隔離級別?

 

列出在SQL標準中,若是設置隔離級別

 

這裏列存各個數據庫引擎,默認的和支持的隔離級別

相關文章
相關標籤/搜索