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