数据库事务系列-事务模型基础
從這篇文章開始,筆者將會在接下來很長時間里整理記錄一個相對獨立的知識領域-數據庫事務,之所以忽然有這個想法,說來也是一種機緣巧合。本來是單純計劃寫寫HBase行級事務模型的具體實現的,但是在周末一不小心看了HBasecon2017里面一個talk之后就一發不可收拾了。這個talk的主題是 Transactions In HBase(作者詳細介紹了基于HBase實現的3種強一致性分布式事務模型-Tephra | Trafodian | Omid),里面提到了Google的Percolater,剛好這個東東是前些天pingcap團隊介紹TiDB時重點提到的一個分布式事務模型(TiDB中的事務模型就是借鑒Percolater實現),就想著好好研究一下這個Percolator,正好也有開源實現可以參考。這兩天晚上看著看著,腦子又想起了兩件事情,第一件事情是筆者在RDS團隊的時候剛好了解記錄過MySQL的單機跨行事務模型,那會理解其實并不算深入,能不能借這個機會徹底弄懂;第二件事情是在考拉基礎組件團隊的時候接觸過基于消息中間件的最終一致性分布式事務模型,雖然不屬于數據庫事務,但也是一種分布式事務實現思路。心想是不是可以把這些事務模型整理成一個系列,一方面是對自己知識體系的一次完善,另一方面可以和更多業界朋友從實際工程實現角度進行分享交流,汲取更多營養。于是就卷起袖子開始擼!
這個系列將從行級事務模型(HBase)開始,然后分析MySQL(InnoDB)的單機跨行事務模型,接著聊聊分布式事務模型。分布式事務模型又分為強一致性模型(Percolator、Omid以及TiDB)和基于補償機制|消息中間件的最終一致性模型。
本篇文章分為兩個部分,第一部分主要介紹一下事務ACID的概念,為后續分析各種事務模型奠定一個基礎;第二部分主要介紹事務中隔離性的相關概念。事務ACID和隔離性在網上有很多解釋版本,筆者接下來的介紹會與網上大體一致,但又不完全相同。如果看官已經了解了相關的概念,可以直接跳過這篇文章。
事務ACID概念
在系統講解事務模型之前,我們首先要弄清楚兩個問題,什么是事務?為什么需要事務?先來看看第二個問題,為什么需要事務,在現實生活中有很多類似于轉賬的操作(A轉1w塊錢到B賬戶,先扣A1w,再給B加1w),比如商品庫存操作(銷售一件商品,首先用戶購物車商品刪除,然后銷售訂單里面增加訂單信息,再者需要將銷售商品庫存減1),再比如評論增加積分操作(首先要在評論表里面增加一條評論信息,再者需要在積分表里面增加相應的積分),這樣的行為不勝枚舉。分析起來,有兩個典型特點,首先這些行為都不是單一操作,都是一系列操作,再者最后對結果的要求是要么全部執行成功,要么完全不執行,不能存在中間狀態,比如轉賬中不能出現A扣減了1w但是B沒有增加1w的場景,否則整個系統狀態就完全混亂。
如果沒有任何機制的保證,計算機在順序執行多個操作(先扣錢、再加錢)的時候一旦發生異常,比如扣錢成功之后、加錢開始之前拋錯,就會出現不可避免的中間狀態。這就是事務存在的意義,那什么是事務呢?數據庫事務(Database Transaction) ,是指作為單個邏輯工作單元執行的一系列操作,要么完全地執行,要么完全地不執行。這個定義摘自百度百科,簡單的說就是,在我們看來扣錢、加錢是兩個操作,但在事務看來就是一個操作。雖說看起來簡單,但是真要成為事務,卻必須滿足ACID屬性:
- A(Atomicity) : 原子性,事務中的一系列操作要么全部完成,要么全部不完成,不能做了一半不做了。這個最好理解,比如轉賬不能扣完A的錢,不給B加錢。
- I(Isolation) : 隔離性,多個事務之間相互隔離的特性。隔離是個很有意思的話題,也是事務模型里面比較復雜的點。首先不同業務對事務的隔離等級要求不一樣,有的嚴格要求隔離,有的并不是那么嚴格。因此數據庫系統都會實現多種隔離級別,從技術角度講,每種隔離級別都需要不同的技術手段來保證,通常來說涉及各種鎖和MVCC機制,后面兩篇文章會重點解釋隔離性。
- D(Durability) : 持久性,事務一旦提交,所修改的數據就會被持久化,后面即使發生任何異常都不會出現數據丟失。這個容易理解,要么數據直接落盤,要么數據操作日志落盤。但是通常情況下數據庫系統也一般會根據數據重要性提供多種持久化策略供客戶端選擇使用,比如對于重要數據,就會要求數據(WAL)同步落盤之后才能算事務完成,這是最嚴格的持久化策略;而對于部分不重要數據,可能只會要求數據(WAL)異步落盤就算事務完成。
- C(Consistency) : 一致性,要求事務必須始終保持系統處于一致的狀態。比如A轉賬給B,轉賬前賬戶總額和轉賬后賬戶總和需要保持一致。
系統的一致性是事務追求的最終結果,無論是原子性、隔離性或者持久性都是保證系統能夠保證一致性的手段。比如一旦原子性無法滿足,事務做到一半退出了,系統必然處于不一致的狀態;再比如有三個小伙伴A、B和C,分別有100元。現有兩個事務分別轉賬,1號事務從A向B轉10元,2號事務從A向C轉50元,如果1號事務或者2號事務對A賬戶不加鎖的話,有可能出現1號事務和2號事務同時扣A的錢,1號事務扣完是90,2號事務正常應該在90的基礎上扣減,但沒有鎖的話,有可能2號事務會在100的基礎上扣減,A的賬戶在兩次扣減結束后變為80元。這種場景就會出現系統不一致,整個事務結束之后A、B和C的總賬戶變成了310元。所以后面我們會討論在事務隔離性實現中存在的各種Write-Write并發控制以及各種鎖,其實很大部分原因就是為了保證事務的一致性要求。另外,如果持久化不能滿足,事務提交之后數據出現了丟失,那系統也必然不一致。
和隔離性以及持久性一樣,一致性也有五花八門的策略:強一致性、最終一致性、session級別一致性、因果一致性等等。強一致性是最容易理解的,在任意時刻整個系統都是一致的;最終一致性是最常見的一種弱一致性模型,簡單的可以理解為一段時間之后,整個系統中的數據會最終達成一致,通常見于分布式系統中保持各個節點之間的數據一致。
隔離性概述
本來下半節文章是要講HBase行級事務模型的,但是構思了一下,發現還是有必要在之前先把隔離性相關的基本概念解釋清楚,后面HBase行級事務、MySQL單機跨行事務就可以專注于技術實現。
上文書提過,不同業務對事務的隔離等級要求并不一致,有的要求很嚴格,有的要求并不是那么嚴格。那通常實現中有哪些隔離等級?目前比較通用的隔離級別主要有4種:Read Uncommitted,Read Committed,Repeatable Read,Serializable。
1. Read Uncommitted
根據字面意思就可以看出,這種隔離級別下1號事務是可以讀到2號事務還沒有提交的數據,我們把這種現象稱為臟讀。臟讀有什么問題?問題其實很嚴重,在很多場景下讀到別人沒有提交的數據,在此基礎上所做的所有假設認知都會是錯誤的,因為這些數據有可能被回滾掉。生活中有大把大把這樣的現象,你以為他訂婚快要嫁人了默默轉身離開,誰知道后來并沒有結婚;你以為他畫餅畫的不錯就死心跟著,誰知道結果沒幾天PPT就做不下去了~ 上圖:
剛開始,1號事務和2號事務看到的A都是A0,接著1號事務將A0更新為A1,再接著2號事務就讀到A1新值,豈料1號事務無情的將A1回滾回了A0。要保證絕對的準確,就不能相信忽悠,讓別人拿事實說事~
2. Read Committed
很顯然,Read Committed是與Read Uncommitted是相對的,意思是說1號事務可以在2號事務提交之后看到2號事務修改的數據。沒錯,這種隔離級別可以避免臟讀,但是又引入了一個新的問題:不可重復讀,如下圖所示:
上圖中2號事務在1號事務更新完成之后讀取A的值依然是A0,避免了臟讀;但在1號事務提交之后再次讀取時發現讀到的值變成了A1,出現了不同時間點對同一數據進行多次讀取,會讀到不同的值的現象。
這在現實生活中有什么問題嗎?其實我覺得并沒有什么問題,畢竟讀的數據是真實的數據,但前后讀到不一致的數據對我們的判斷產生很大的影響。比如A同學看了看最近的任務排期,發現沒有事情干了,于是就請假陪女朋友去巴厘島旅游,剛到巴厘島,掃了一眼郵件再次查看任務排期,發現leader發了一封緊急郵件,說要全員加班臨時趕一個項目。A同學看到這封郵件的時候只能對著女友強顏歡笑…然后帶女朋友買她最喜歡的LV~
所以最理想的就是我第一次看任務排期和我旅行期間再次看任務排期最好都是一樣的,這樣就可以保證本次旅行絕對happy。之后的事情之后再看嘍。這就是接下來要介紹的可重復讀~
3. Repeatable Read
從字面意思來看這種隔離級別修復了不可重復讀這樣的問題,表現如下圖所示:
可以看出,無論1號事務如何更新A,2號事務在隨后的進程中看到的A值都是事務開始第一次看到的A值(A0)。雖然解決了不可重復讀的問題,但是還有一個問題-幻讀:
上圖中1號事務在事務過程中插入了一個大于B0的新值B2,2號事務在插入操作前后讀取B > 0的時候讀到的值卻不同。那問題來了,幻讀會在現實世界中引起什么樣的嚴重后果嗎?其實和不可重復讀是一樣的道理,前后讀到的數據不一致會對當前的事情進展產生影響,不過幻讀發生的場景相對少一些。
MySQL的童鞋需要注意,此處介紹和MySQL(InnoDB)中RR級別有些許不一樣,MySQL中RR級別比較特殊,同時能夠保證不可重復讀和幻讀。具體實現在接下來的文章《數據庫事務系列-MySQL跨行事務模型》中會講到。
4. Serializable
串性化是隔離最嚴格的一種形式,要求有讀寫沖突的事務必須嚴格串行執行。如下圖所示,2號事務要讀取1號事務修改的記錄A,這就導致2號事務必須等待1號事務提交之后才能開啟執行。通過這種形式可以避免之前所提到臟讀、不可重復讀和幻讀。雖說如此,幾乎所有數據庫業務都不會開啟這種隔離級別,因為這會帶來嚴重的鎖沖突。接下來幾篇文章中涉及技術實現會再詳細解釋。
好了,本文主要介紹了數據庫事務系列文章的概括,數據庫事務的基本概念和ACID,最后介紹了各種隔離級別。接下來會進入具體數據庫系統,分別介紹HBase行級事務模型、MySQL單機跨行事務模型以及其他分布式強一致性事務模型~
本文轉載自:http://hbasefly.com
原文鏈接
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的数据库事务系列-事务模型基础的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大数据助力智慧城市建设
- 下一篇: 大数据分析助精准医疗迅猛发展