iT邦幫忙

2021 iThome 鐵人賽

DAY 7
0
AI & Data

資料工程師修煉之路 Part II系列 第 7

Transactions (5-2) - Serializability Isolation - SSI & Summary

Day 6

強列建議閱讀本文之前要先去看 Day 4 - Snapshot Isolation

3. 序列化快照隔離 SSI (Serializable Snapshot Isolation)

難道 序列化隔離 (serializable isolation) 跟良好效能是矛盾的嗎?

在這裡跟您介紹 序列化快照隔離 (Serializable Snapshot Isolation) ,一種比快照隔離多了一點開銷的算法,但它提供了完整的序列化功能,它來自於 2009 年 Michael Cahill's 的博士論文

悲觀 (Pessimistic) 和樂觀 (Optimistic) 並發控制

二階段鎖 (Two-Phase Locking) 看上去可以被稱為悲觀的並發控制機制,悲觀的大原則是說凡是有可能錯的就一定會出錯,也就是像 2PL 那樣要取得 互斥模式 (exclusive mode) 鎖才能寫入資料,其他人最好還是乖乖等我!

連續執行 (Serial Execution) 更是悲到極致了,它本質上等同於每個 transaction 都得獲取整個資料庫的互斥鎖才能做事情。

相比之下序列化快照隔離就是屬於樂觀的並發控制機制,樂觀代表它不假設潛在的危害會發生,它希望一切都會好轉;當一個 transaction 想要 commit 時,資料庫才會檢查是否有不好的事情在發生(例如隔離無效),如果有,則該 transaction 會中斷且重試。

就像命名那樣,序列化快照隔離的基礎是快照隔離,所有的讀取都是來自有一致性的資料庫快照中 (Day 4 - Snapshot Isolation),而最大的不同是序列化快照隔離多新增了一個演算法,在寫入期間去檢測是否發生連續的衝突然後決定哪個 transaction 要被中斷。

基於過時前提的決策

如同我們在 Day 5 提過的,快照隔離可能會發生 write skew ,其模式就是 查詢-判斷-寫入,在 commit 時其原始查詢結果可能 不再是最新的,因為該資料可能同時被其他 transaction 修改。

換一種方式來說,這些 transaction 是基於一種 前提 來執行,以 Day 5 - 醫生 oncall 案例 來看,前提就是:目前正有 2 個醫生在 oncall,爾後在 commit 時,這個前提可能就不是為真了。

但資料庫怎麼知道應用程式對查詢結果的判斷邏輯為何呢?為了安全起見,資料庫會假設所有的查詢結果都可能都會被改變(查詢結果 = 前提),意味者該 transaction 的寫入可能會無效。

資料庫必須檢測 transaction 的前提是否過時,所以這裡有 2 個狀況需要考慮:

  • 檢測從腐敗 MVCC 物件版本讀取的資料(未 commit 的寫入發生在讀取之前)。
  • 檢測讀取期間的寫入(寫入發生在讀取之後)。

檢查腐敗的 MVCC 讀取

回憶一下 MVCC 的機制,當 transaction 從一致的快照讀取資料時,它會忽略其他未 commit 的 transaction 寫入,如下圖 7-10 (使用 Day 5 - 醫生 oncall 案例),transaction 43 讀取到的資料是 Alice on_call=true,因為 transaction 42 還沒 commit,然而,當 transaction 43 想要 commit 時,transaction 42 已經 commit 了,這意味者 transaction 43 commit 會被忽略,transaction 管理者會注意到快照資料已被影響,且 前提 的值不再是最新的了。

檢測讀取期間的寫入

現在來看第 2 個情況,如下圖 7-11,transaction 42 和 43 都查詢了 shift_id=1234 的班,如果這裡有個 shift_id 的 index,資料庫就會借用 index 進入點 1234 來記錄 transaction 42 和 43 正在讀取資料(如果沒有 index 就會追蹤在 table 等級中),其資料會保留到所有並發 transaction 都結束後才會清除。

當 transaction 寫入到資料庫時 ,它必須看一下 index 資料內是否也有正在讀取的資料被影響,transaction 42 和 43 會彼此留意資料有可能不再是最新的,所以 transaction 43 想要 commit 時,transaction 42 已 commit 所以發生衝突,故 transaction 43 被中斷了。

序列化快照隔離 (Serializable Snapshot Isolation) 的效能

樂觀並發控制在有非常高度競爭時(多個 transaction 嘗試存取相同物件)會表現的比較不好,代表了會有很多的片段 transaction 會需要被中斷。

但是跟 二階段鎖 (Two-Phase Locking) 比起來,序列化快照隔離有個最大的優勢就是 transaction 的寫入不用阻檔等待從其他 transaction 取得鎖,就像快照隔離那樣,寫入跟讀取不會互相影響,這個設計原則讓查詢延遲 (lantency) 變的可預測且變化較小,read-only 類型的查詢可以從一致的快照讀取資料而不需要取得任何鎖,適合用在讀取重的場景上。

而跟 連續執行 (Serial Execution) 比較呢?序列化快照隔離不必被限制上單一 CPU core 的吞吐量多少了。

影響序列化快照隔離效能最大的就是中斷的比率,所以它當然也希望所有 transaction 都是短小精幹(長時間只讀不寫的 transaction 也許 Ok);總而言之,它對緩慢 transaction 的敏感度遠遠小於 二階段鎖 跟 連續執行。

Summary

transaction 重要,但更重要的是挑選適合業務規則的資料庫,希望 Day 1~Day 7 的 transaction 能幫助你們更了解一點。

總結這麼短是因為字數夠了 XD


上一篇
Transactions (5-1) - Serializability Isolation - Serial & 2PL
下一篇
Trouble with Distributed Systems (1)
系列文
資料工程師修煉之路 Part II30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言