本文為 Design Data Intensive Applications 的書摘 + 個人心得。
在莫非定律的魔爪下,一個應用系統都有可能遇到下列幾種錯誤:
- 資料庫的軟體或硬體忽然掛掉。
- 應用系統端(Application)忽然掛掉。
- 系統跟資料庫的網路斷掉,或者各資料庫節點的網路斷掉。
- 同時多個客戶端想修改資料庫資料。
- 某個客戶端讀取到奇怪的資料,因為該資料是部份更新成功。
transaction (事務) 的概念就是讓上述問題 簡單化,transaction 就是一個方法讓應用系統把數個讀取和寫入集結成一個邏輯單位,白話點說就是同一個 transcation 的多次讀取跟寫入會視為一個操作,就只有成功 (commit) 或失敗 (abort, rollback) 兩種結果;若發生失敗,有關資料是否更新的疑慮通通消失,你的後續動作就變的簡單多了。
幾乎所有的關聯式資料庫 + 少部份的 NoSQL 支援 transaction,就像所有技術決定一樣,transaction 有它的優點跟限制,並不是所有的應用系統都需要 transaction,也不是用了 transaction 就一定比較慢,更沒有 transaction 非得用在 有價值 的資料上,所以在做各種權衡前,務必要了解各種 transaction 的概念與機制。
ACID
transaction 的安全保證來自 原子性 (Atomicity)、一致性 (Consistency)、隔離性 (Isolation) 和 持久性 (Durability),由 1983 年的 Theo Härder 和 Andreas Reuter 提出,但時至今日,ACID 這詞變的很曖昧,同樣的詞可能會代表不同意思,接下來會詳述 ACID 通用的定義和該改什麼名詞比較好 XD
原子性 (Atomicity)
一般來說,原子性 意為某樣東西不可在被切割的更小塊。
但在計算機領域中,則是指在多執行緒底下,某個執行緒若執行一個原子操作 (atomic operation),另一個執行緒無法看到該操作中的半完成狀態,只有操作前跟操作後兩個狀態。
就 ACID 的角度來看,原子性跟並發 (concurrent) 一點關係都沒有(跟並發有關的是 隔離性),原子性描述的是當多次寫入有錯誤發生時(無法 commit,且有幾筆已成功寫入),transaction 會中斷,資料庫會捨棄或回復成原始的資料,應用系統端可以確保不會有任何資料被寫入,所以他們可以放心的重試。
書中就說,用中斷性 (Abortability) 來代表 A 會比較適合。
一致性 (Consistency)
這個的定義可多了,簡單舉例就有:
- Leaders and Followers – Problems with Replication Lag 中的最終一致性 (eventual consistency)。
- 一致性雜湊 (Consistent Hashing)。
- CAP 理論的 Consistency。
- ACID 角度的 Consistency。
ACID 的 一致性 指的是在你對你資料的某種陳述底下,其資料必定符合該陳述。
什麼意思呢?假設有個會計系統,你的資料中有借就會有貸,借貸必定平衡,所以一個 transaction 成功時,其必定滿足這個陳述。
然而,這個 一致性 的概念是需要仰賴應用系統來定義的,其實跟資料庫要提供的 transaction 安全保證沒啥關係,你若想寫髒資料,資料庫也管不到你,所以啦,資料庫其實只需要 原子性、隔離性 和 持久性 就能確保應用系統端想符合的一致性。
隔離性 (Isolation)
隔離性 指的是當 transaction 在並發執行時,其 transaction 不會互相影響。
下圖 7-1 是個例子來說明對同一筆資料的並發操作問題,你有 2 個 User 同時去將 counter + 1,最終的 counter 應該要 44, 而不是 43。
教科書等級的隔離 是 序列化隔離 (serializability isolation),意思是每次在資料庫中,只會有一個 transaction 在執行,做完才換下一個,但實務上不會這樣幹,對效能的影響很大,大多都會使用較弱的 弱等級的隔離 (Weak Isolation Levels)(之後介紹)。
持久性 (Durability)
持久性 是保證一但 transaction 成功 commit,資料不會被忘記,即使硬體壞掉或資料庫掛掉。
對單機器的資料來說,持久性 就是成功寫到硬碟或 SSD 上,對多節點有 數據複製 (replication) 的資料庫來說,持久性 就代表了有成功複製資料到其他節點上了。
明天會談談資料物件之更新會用到哪些 ACID 原則。