pg事务:隔离级别历史与SSI
事務隔離級別的歷史
ANSI SQL-92定義的隔離級別和異常現象確實對數據庫行業影響深遠,甚至30年后的今天,絕大部分工程師對事務隔離級別的概念還停留在此,甚至很多真實的數據庫隔離級別實現也停留在此。但后ANSI92時代對事物隔離有許多討論甚至批評,針對隔離級別和異?,F象的論文、博客、文章、討論非常多,這里概況一下事務的比較重要發展歷史:
-
1992年,由于數據庫行業處于混沌的事務狀態,美國國家標準學會定義ANSI SQL-92標準。也就是廣泛流傳的4種隔離級別和4種異?,F象
-
1995年,snapshot isolation等隔離級別提出和更多的異?,F象。微軟工程師等提出snapshot isolation隔離級別,并對ANSI SQL-92做出批判,92標準定義模糊,而且有許多隔離級別和異?,F象未定義。參考《對ANSI SQL隔離級別的批判》.
此時隔離級別已不止4個,異?,F象也更多,其中也包括寫偏序異常。
-
1999年 ,由于鎖模式的不同發展出過多的隔離級別,Atul Adya的論文整理了這些現象,并根據異?,F象和功能將眾多隔離級別回溯到ANSI SQL92標準進行對應。
-
2005年 ,由于絕大部分數據庫聲稱他們是可串行化的,但他們實際上是快照隔離, Alan Fekete et al 提出“使快照隔離可序列化”。在snapshot isolation級別基礎上實現可序列化,消除快照隔離的異象。
-
2008年 ,Fekete 擴展了可序列化,并提出數據庫層面實現“使快照隔離可序列化”,稱之為快照隔離可序列化SSI (Serializable Snapshot Isolation)
-
2012年 ,postgresql第一個在數據庫中實現SSI ,參考postgresql數據庫實現SSI的論文
其中,95年《對ANSI SQL隔離級別的批判》中的隔離級別和異常現象
各種數據庫支持的隔離級別
很多數據庫的聲稱他們”完全支持ACID“特性,但是沒有可串行化是不能完全實現ACID的(特別是一致性)。然而許多數據庫在不支持可串行化級別下聲稱他們支持ACID。其實他們絕大部分都沒有完全實現,包括數據庫老大哥oracle。
可串行化
人們對可串行化存在許多誤解。
可串行化的含義:如果每個事務本身是正確的,即滿足某些完整性條件,那么包括這些事務的任何串行執行的時間表是正確的(其事務仍然滿足其條件):“串行”意味著事務在時間上不重疊,并且不能相互干擾,即彼此之間存在完全隔離。
1970年代可串行化(serializable)通過嚴格兩階段鎖(SS2PL)實現,讀寫相互阻塞,直到事務結束。SS2PL丟失高可用性但消除了異?,F象。
除了SS2PL實現可串行化,還有其他方式,比如可串行化快照隔離(SSI)。
為了保證沒有異常,可串行化會丟失一些并發性(不同實現方式有所不同),但可以真正保證數據的一致性(ACID中的consistency)。也就是說沒有實現串行化的數據庫,其實沒有完全支持ACID特性
可串行化在數學上已經證明可以實現,但是真實的數據庫世界有點”不正?!?。實際上,可串行化是事務隔離級別中最高級的,也是所有學者和大佬強力推薦的隔離級別,不過絕大部分數據庫在RC或快照隔離級別上運行
為什么弱隔離級別在學術上有問題,實際上沒出現嚴重問題?
1.非可串行化隔離級別的異?,F象,一般都需要再高并發情況下才會發生,一般低并發數據庫不太會出現問題
2.異?,F象真的發生的時候,有些應用可能沒發現異?,F象或沒檢查到異常對他們不重要。
3.有可能數據異常了,但應用只是返回報錯,并進入數據異常處理程序。
4.成本過高。不僅是數據庫序列化隔離級別開發成本高,應用對可序列化也需要適應成本。光是理解這部分復雜的理論就不是一件容易的事
5.高級別的隔離會丟失一些性能。大量的改造工作可能是吃力不討好的,應用需要在“高并發”和“無異常現象”間做抉擇
6.業務基于機制開發,而不是規則開發。業務多少有點適應弱隔離級別的異?,F象,特別是RC或快照隔離級別
快照隔離
ANSI SQL92并未定義快照隔離snapshot isolation(SI),這個隔離級別隨著數據庫行業發展才出現。
引自wiki定義:在快照隔離下執行的事務是在事務開始時拍攝的數據庫的快照上操作的。當事務結束時,只有當事務更新的值自快照拍攝以來沒有外部更改時,它才會成功提交。這樣寫沖突將導致事務中止。
快照隔離級別顧名思義就是就是使用了快照,存在于使用了MVCC的數據庫中,多版本并發機制支持用戶并發執行事務。
1992年 ANSI SQL92標準基于數據庫的鎖而定義,所以沒有快照隔離級別這個定義。直到1995年《批判》的出現才被提出。
快照隔離串行化
由于快照隔離的廣泛應用,而可序列化是學術上的數據庫需要達到的隔離級別目標,可序列化快照隔離Serializable Snapshot Isolation (SSI) 隨即產生。顧名思義,在快照隔離的基礎上實現可序列化。
由于ANSI92標準的模糊性,雖然沒有定義快照隔離,但許多數據庫實際上就是使用的快照隔離。而快照隔離同樣存在一些異常現象(包括寫偏序),SSI的出現就是為了解決這些異?,F象。
主流數據庫通過基于S2PL或MVCC實現并發控制。在S2PL下寫操作會阻塞其他事務讀寫,因此不會有寫偏序異常問題。而MVCC實現了讀寫互不阻塞,只有寫寫沖突。在并發RW模式模式下會導致寫偏序問題。SSI在pg9.1開始已經嵌入快照隔離SI中(pg只有快照隔離,哪怕是在可序列化級別下),解決了寫偏序等異常。
寫偏序
由于某些沖突構成環,會出現串行化異常**。**其中比較容易理解的一個就是寫偏序(write skew)。
寫偏序只發生在rw模型,ww、wr均不會發生寫偏序,并且事務必須在并發條件下才會出現。前一個事務寫入依賴后一個事務寫入才會形成依賴環。
有許多現實案例可以出現寫偏序異常,我們用一個經典的黑白球問題來理解寫偏序
袋中有10個球,5個白球和5個黑球。此時有兩個事務,P和Q。P將所有黑球改成白球,Q將所有白球改成黑球。此時可以有兩個串行執行,P,Q或Q,P。在這兩種情況下,最終結果是袋中有10個白球或者10個黑球。但是,快照隔離允許另一種結果:
- 事務 P 拿出5個黑球
- 事務 Q 拿出5個白球
- 事務 P 將手中所有黑球改成白球,放回袋中
- 事務 Q 將手中所有白球改成黑球,放回袋中
此時袋中還是5個黑球和5個白球,這在任何一個串行執行中都是不可能的。但這在快照隔離中是有效:每個事務都維護數據庫的一致視圖,并且其寫集不與任何并發事務的寫集重疊,如此白球黑球發生交換。
黑白球問題說明:快照隔離執行結果與串行化執行結果不一致,快照隔離下發生寫偏序異常,數據結果與預期不一致。
pg中的SSI
postgresql數據庫是首個在數據庫中實現SSI的數據庫。
引用wiki的黑白球代碼示例
create table dots(id int not null primary key,color text not null);insert into dotswith x(id) as (select generate_series(1,10))select id, case when id % 2 = 1 then 'black'else 'white' end from x;| begin; update dots set color = ‘black’ where color = ‘white’; | |
| begin; update dots set color = ‘white’ where color = ‘black’; | |
| commit | |
| commit | |
| (pg SSI先提交者成功提交,后提交者拋出報錯 ) | ERROR: could not serialize access due to read/write dependencies among transactions DETAIL: Reason code: Canceled on identification as a pivot, during commit attempt. HINT: The transaction might succeed if retried. |
(已提交讀和可重復讀級別,均不會出現報錯,黑白球顏色交換,不再展示測試結果)
嚴格兩階段提交(S2PL)也可以實現可串行化,但S2PL需要很重的讀寫鎖,直到事務提交為止。S2PL會極大的影響并發性能,而且用戶一般不會接受讀寫互相阻塞的情況,所以pg沒有采用S2PL。
SSI是可序列化的另一種方案。它仍然會使用快照隔離,只是會額外檢查是否有異?,F象發生。
兩個方案的處理方式也不同:在異?,F象發生時,S2PL會阻塞事務,而SSI會中斷事務以打破循環。
人們沒有使用可串行化,原因之一有可串行化會降低數據庫性能。這其實可以理解,因為有”檢查異?,F象“的SSI必定比什么檢查都沒有的弱隔離級別性能低。不過經過SSI實現理論的發展和pg本身對只讀事務的優化,SSI的性能已于SI相差無幾。
可序列化能極大的簡化應用對一致性的擔心,而pg9.1已實現ssi并加以優化。期待應用有一天真的能使用可串行化隔離級別。
事務隔離級別參考
https://wiki.postgresql.org/wiki/SSI
https://en.wikipedia.org/wiki/Serializability
https://en.wikipedia.org/wiki/Snapshot_isolation
https://justinjaffray.com/what-does-write-skew-look-like/
http://www.bailis.org/blog/when-is-acid-acid-rarely/
https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tr-95-51.pdf 95年SI隔離級別以及對SQL92標準的批評
https://www.cse.iitb.ac.in/infolab/Data/Courses/CS632/2009/Papers/p492-fekete.pdf SSI論文
https://drkp.net/papers/ssi-vldb12.pdf postgresql實現SSI
https://ristret.com/s/f643zk/history_transaction_histories 事務隔離級別的歷史
總結
以上是生活随笔為你收集整理的pg事务:隔离级别历史与SSI的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python将一张图片粘贴到另外一张图片
- 下一篇: MFC 108问题