寫在前面
本文是一篇CockroachDB官方博客的譯文,主要闡述數據庫實現串行化隔離的必要性。關於事務隔離性,Ivan曾經在“分布式數據庫之事務隔離性”中從理論方面進行過系統的介紹,本文則是從數據庫廠商的角度來闡述對隔離性的理解,大家可以將兩篇文章結合起來,對隔離性有更加全面客觀的理解。CockroachDB的理念是首先保證安全性而后追求高性能,所以花了很大精力實現Serializable Snapshot Isolation
,是目前極少的有實用價值的SERIALIZABLE
實現。當然,業界也有廠商對可串行化方面投入的必要性持不同觀點。Ivan猜測CockroachDB的理念可能是受到了PostgreSQL的影響,畢竟后者是率先支持Serializable Snapshot Isolation
的商業數據庫,並且CockroachDB在SQL層面也是以兼容PostgreSQL為目標。
正文
大多數數據庫都提供了事務隔離級別的選擇,可以在正確性和性能之間進行權衡。然而,高性能的代價就是開發人員必須小心研究事務交互否則就會引入一些微妙的錯誤。CockroachDB 默認提供了強隔離(SERIALIZABLE
)可以確保你的應用總是看到期望的數據。在本文中我們將解釋這意味着什么以及不充分的隔離在如何影響真實世界的應用。
SQL標准中的隔離性
SQL標准定義四個隔離級別
-
SERIALIZABLE
-
REPEATED READ
-
READ COMMITTED
-
READ UNCOMMITTED
SERIALIZABLE
事務運行時好像在同一時刻僅有一個事務運行;其他隔離級別允許出現SQL標准稱作的“三種phenomena”臟讀、不可重復讀、幻讀。后續的研究(此處指Critique,Ivan在文章“分布式數據庫之事務隔離性”中已經進行了介紹)定義了額外的“phenomena”和隔離級別。
在現代研究中,這些“phenomena”更普遍被稱為“anomalies”,或者更直接稱為”lies”。當你使用一個非SERIALIZABLE
隔離級別時,你是在允許數據庫返回錯誤答案,希望它能比正確答案更快。SQL標准認為這是危險的,需要SERIALIZABLE
置為默認的隔離級別。更弱的隔離級別只是為那些可以容忍“anomalies”的應用提供了潛在的優化手段。
真實數據庫中的隔離性
多數的數據庫忽略了將 SERIALIZABLE
作為默認隔離級別的規約,而是默認替換為更弱的RC
或RR
隔離級別,它們的性能優先於安全性。更令人擔心的是,一些數據庫(包括Oracle,PostgreSQL V9.1以前)根本不提供 SERIALIZABLE
級別的事務隔離。Oracle實現的 SERIALIZABLE
隔離級別實際上是更弱的“Snapshot Isolation
”。Snapshot Isolation
(快照隔離,簡稱SI
)的出現晚於SQL標准的制定,但是已經被多種數據庫系統實現,因為它提供了很好的性能與一致性的平衡。它強於RC
但弱於 SERIALIZABLE
,很類似RR
但不完全等同(RR
允許幻讀,但禁止寫偏序,SI
更好相反)。實現SI
的數據庫,在如何將其納入到四個SQL標准隔離級別上有不同的選擇。Oracle的選擇最激進,直接將他們的SI
實現稱為 SERIALIZABLE
。CockroachDB 和SQL Server則保守一些,將SI
作為獨立的第五個隔離級別。PostgreSQL(9.1版本以后)介於兩者之間,使用SI
替換了RR
。因為數據庫很少使用 SERIALIZABLE
模式,而是默認采用更弱的隔離級別,所以它通常很少經過徹底的測試和優化。例如PostgreSQL有一個固定大小的內存池,用來跟蹤可串行化事務間的沖突,但在高負載情況下會耗盡。
多數的數據庫廠商將更強的事務隔離作為給應用程序的一個特殊選項用於應對額外的一致性需求。多數應用程序被認為可以運行在更快但是不安全的弱隔離模式下。這種處理問題的落后方式導致將應用程序暴露在大量細微的bug中。在Cockroach Labs,我們喜歡思考事務anomalies,以至於我們用它們來命名會議室。但我很難有信心的建議什么時候選擇 SI
替代 SERIALIZABLE
是安全有益的。
我們的哲學是從安全性出發向着高性能方向前進,這是比其他方式更優的。
ACIDRain:發現事務Bug
斯坦福最近的研究展示了弱隔離性對真實世界的影響程度。 Todd Warszawski and Peter Bailis測試了12個電子商務應用程序並發現了22個事務相關的Bug,其中5個在更高的隔離級別下可以避免。多數bug可以被簡單得利用並造成財務方面的影響。例如,在5個被測試的應用程序中,當操作一個瀏覽器進行結算的同時,操作另一個瀏覽器向購物車增加一項商品,可能導致新增的商品在賬單中免費。這些研究人員開發工具以半自動化的方式去確定這些脆弱點,為類似的更普遍的攻擊(研究者將其稱為ACIDRain “酸雨”)鋪平了道路。
大多數默認弱隔離的數據庫都提供了解決方法,例如 FOR UPDATE
和 LOCK IN SHARE MODE
(非標准語法)作為SQL語句的修飾符。當正確使用時,即使在弱隔離級別下,這些修飾符也可以使事務安全。然而,這很容易出錯,而且即使是使用這些擴展方式,也會同時引入 SERIALIZABLE
模式大多數的缺點。(事實上,在RC
事務中濫用 SELECT FOR UPDATE
可以導致比 SERIALIZABLE
更差的性能,因為在那些串行化操作的地方可以僅使用共享鎖,卻使用了排他鎖) ACIDRain的研究顯示了這種技術的局限性:3個應用程序中僅有一個正確使用了 SELECT FOR UPDATE
特性,其他兩個都存在漏洞。
結論
鼓勵弱隔離級別(性能優先於數據安全性)的數據庫,讓你去學習事務間細微的交互並實現易錯的解決方法。CockroachDB默認提供了 SERIALIZABLE
事務,確保總能看到你所期望的事務數據庫的一致性
原文鏈接 https://www.cockroachlabs.com/blog/acid-rain/