1. 程式人生 > 實用技巧 >極客時間 分散式資料庫 筆記02

極客時間 分散式資料庫 筆記02

10 | 原子性:如何打破事務高延遲的魔咒?

並行執行的過程是這樣的。

準備階段的操作,在 CockroachDB 中被稱為意向寫。這個並行執行就是在執行意向寫的同時,就寫入事務標誌,當然這個時候不能確定事務是否提交成功的,所以要引入一個新的狀態“Staging”,表示事務正在進行。那麼這個記錄事務狀態的落盤操作和意向寫大致是同步發生的,所以只有一輪共識演算法開銷

而客戶端得到所有意向寫的成功反饋後,可以直接返回呼叫方事務提交成功。注意!這個地方就是關鍵了,客戶端只在當前程序內判斷事務提交成功後,不維護事務狀態,而直接返回呼叫方;事後由非同步執行緒根據事務表中的線索,再次確認事務的狀態,並落盤維護狀態記錄。這樣事務操作中就減少了一輪共識演算法開銷。

11|隔離性:讀寫衝突時,快照是最好的辦法嗎?

所以說,用鎖解決讀寫衝突問題,帶來的事務阻塞開銷還是不小的。相比之下,用 MVCC 來解決讀寫衝突,就不存在阻塞問題,要優雅得多了

從上面的例子可以發現,RC 與 RR 的區別在於 RC 下每個 SQL 語句會有一個自己的快照,所以看到的資料庫是不同的,而 RR 下,所有 SQL 語句使用同一個快照,所以會看到同樣的資料庫。

為了提升效率,快照不是單純的事務 ID 列表,它會統計最小活動事務 ID,還有最大已提交事務 ID。這樣,多數事務 ID 通過比較邊界值就能被快速排除掉,如果事務 ID 恰好在邊界範圍內,再進一步查詢是否與活躍事務 ID 匹配。

CockroachDB 沒有使用快照,不是因為沒有全域性事務列表,而是因為它的隔離級別目標不是 RR,而是 SSI,也就是可序列化

CockroachDB 的每個事務都有一個優先順序,出現事務衝突時會比較兩個事務的優先順序,高優先順序的事務繼續執行,低優先順序的事務則被重啟。而被重啟事務的優先順序也會提升,避免總是在競爭中失敗,最終被“餓死”

12 | 隔離性:看不見的讀寫衝突,要怎麼處理?

還有一種看不見的讀寫衝突,它是由於時間的不確定性造成的,更加隱蔽,處理起來也更復雜

只有避免時間窗口出現重疊。 那麼如何避免重疊呢?

答案是等待。“waiting out the uncertainty”,用等待來消除不確定性

寫等待的處理方式是這樣的。事務 Ta 在獲得“提交時間戳”S 後,再等待ɛ時間後才寫盤並提交事務。真正的提交時間是晚於“提交時間戳”的,中間這段時間就是等待。這樣 Tb 事務啟動後,能夠得到的最早時間 TT2.earliet 肯定不會早於 S 時刻,所以 Tb 就一定能夠讀取到 Ta。這樣就符合線性一致性的要求了。

綜上,事務獲得“提交時間戳”後必須等待ɛ時間才能寫入磁碟,即 commit-wait。

2PC 的第一階段是預備階段,每個參與者都會獲取一個“預備時間戳”,與資料一起寫入日誌。第二階段,協調節點寫入日誌時需要一個“提交時間戳”,而它必須要大於任何參與者的“預備時間戳”。所以,協調節點呼叫 TT.now() 函式後,要取該時間區間的 lastest 值(記為 s),而且 s 必須大於所有參與者的“預備時間戳”,作為“提交時間戳”

針對同一個資料項,事務 T8 和 T9 分別對進行寫入和讀取操作。T8 在絕對時間 100ms 的時候,呼叫 TT.now() 函式,得到一個時間區間[99,103],選擇最大值 103 作為提交時間戳,而後等待 8 毫秒(即 2ɛ)後提交。

這樣,無論如何 T9 事務啟動時間都晚於 T8 的“提交時間戳”,也就能讀取到 T8 的更新

寫等待模式下,所有包含寫操作的事務都受到影響,要延後提交;而讀等待只在特殊條件下才被觸發,影響的範圍要小得多。

在這個過程中,可以看到讀等待的兩個特點:一是偶發,只有當讀操作與已提交事務間隔小於設定的時間誤差時才會發生;二是等待時間的更長,因為事務在重啟後可能落入下一個不確定時間視窗,所以也許需要經過多次重啟。

13 | 隔離性:為什麼使用樂觀協議的分散式資料庫越來越少?

樂觀協議就是直接提交,遇到衝突就回滾;悲觀協議就是在真正提交事務前,先嚐試對需要修改的資源上鎖,只有在確保事務一定能夠執行成功後,才開始提交。

當然,為了避免這種情況的出現,TiDB 的樂觀鎖約定了事務的長度,預設單個事務包含的 SQL 語句不超過 5000 條。但這種限制其實是一個消極的處理方式,畢竟業務需求是真實存在的,如果資料庫不支援,就必須通過應用層編碼去解決了

另外,悲觀鎖還觸發了一個變化。TiDB 原有的事務模型並不是一個互動事務,它會把所有的寫 SQL 都攢在一起,在 commit 階段一起提交,所以有很大的並行度,鎖的時間較短,死鎖的概率也就較低。因為增加了悲觀鎖的加鎖動作,變回了一個可互動事務,TiDB 還要增加一個死鎖檢測機制。

14 | 隔離性:實現悲觀協議,除了鎖還有別的辦法嗎?

強兩階段封鎖協議(Strong Strict 2PL,SS2PL),事務一直持有已經獲得的所有鎖,包括寫鎖和讀鎖,直到事務終止。SS2PL 與 S2PL 差別只在於一直持有的鎖的型別,所以它們的圖形是相同的。