李雷和韓梅梅的一次轉帳事務–事務系統概述

上次咱們在最後一部分,給出了一個事務操做的模型和內部簡單實現的方式,以期讓你們能針對事務有一個比較簡單的印象。今天,我就嘗試針對事務的基本特性作一個簡單的概述。固然,由於仍然是概述,因此不會特別深刻的去介紹和分析內部的機制,只但願可以將一些難以理解的概念,用舉例子的方式協助你們可以更容易的理解事務的基本概念。

談到事務,咱們要作的第一件事,就是理解,什麼叫作事務,以及爲何要有事務。html

事務這個概念的產生,仍然是爲了解決咱們在以前提到的打字機問題:
(面試

http://blog.sina.com.cn/s/blog_693f08470101l1n1.html)數據庫

像咱們在上文中提到的,計算機只是一個圖靈機,因此,若是計算機要實現咱們現實的世界的一些操做模式,只能靠模擬的方式進行。上次咱們是使用鎖來處理一次寫請求過程裏面對應的屢次計算機操做的時候怎麼看起來像是一次總體的操做。而在這裏咱們要解決的問題是,一組用戶的屢次寫入和讀取操做,怎麼可以被看起來像是一次總體的操做呢?首先,讓我用個例子來看看爲何須要這樣作。

爲了後面敘述方便,讓咱們先設定一個實際的環境場景:
梅梅給李雷打了一個電話,說最近想買一本英語書,須要一百元,李雷得知梅梅的請求,二話不說就開始操做他的網銀給梅梅作了轉帳付款:

假定李雷帳戶是pk=1,韓梅梅的帳戶是pk=2
begintransaction;
{查看李雷是否有一百元}
selectcashfromTwherepk=1;A操做
{肯定有足夠的錢,減小李雷的錢}
updateTsetcash=cach-100wherepk=1;B操做
{給韓梅梅增長一百元}
updateTsetcach=cash+100wherepk=2;C操做
commit;好,我想我針對事務場景的場景應該描述清楚了。

首先咱們來介紹原子性服務器

從業務需求來講,咱們必須保證,只要李雷的帳戶減小了100塊,那麼這一百塊必須可以加到韓梅梅的帳戶裏。若是中間有任何一個操做失敗,系統不可以憑空多出一百元(李雷沒有減錢,韓梅梅卻加了錢),也不能憑空少了一百元(李雷減小了一百元,韓梅梅帳戶卻沒增長)。
爲了作到這個特性,就必須保證李雷帳戶減錢與韓梅梅帳戶加錢這兩件事,要麼同時成功,要麼同時不成功。
這就是事務中的第一個重要的概念:原子性的含義分佈式

下面咱們來介紹一致性
當看到本身的帳戶減小了一百塊之後,李雷問電話那頭的梅梅:「梅梅,我看我這裏操做成功了,你那裏收到錢了沒?」。若是這時候梅梅跟李雷說:」雷~我沒看見我帳戶的錢有變化啊「。
想想,這時候李雷會是什麼感受?他的內心必定會」咯噔「一下,錢不會是丟了吧?趕忙給支付寶打電話確認怎麼回事!ide

這裏的這種狀況,就是一致性沒有保證而可能出現的一種狀況,簡單來講,就是其餘用戶看到了事務三步操做過程當中的中間狀態信息,這種信息是明顯反用戶常識的,因此應該儘量被避免。
所以我作個簡單小結,這裏咱們須要可以保證,當李雷看到本身帳戶減小了100元的時候,韓梅梅的帳戶裏也必須可以看到增長了一百元。
這種要麼同時出現,要麼同時消失的保證,就是事務一致性。在看到這裏的時候,相信必定會有人來問,這個一致性和原子性,看起來都是要麼成功,要麼不成功的感受,那麼這兩個概念有什麼差別呢?

恩,下面我就來嘗試解決這個疑惑吧~
區分這倆概念的關鍵,其實在一個」看」字,一致性約束的是一個用戶寫入並提交數據以後,其餘用戶去去讀這條記錄的時候,要麼看到的是李雷尚未給韓梅梅轉帳的那個狀態,要麼就是李雷已經成功轉帳給了韓梅梅的狀態,而在這兩個狀態之間的事務狀態,好比李雷減小了100元,但韓梅梅還沒加上這一百塊的這個中間狀態則不可以被其餘人看到。而原子性只須要保證操做要麼」最終「所有成功,要麼」最終「所有失敗而已。原子性不約束可見性,只保證操做的邏輯性。
這,就是一致性和原子性保證的差異。性能

最後,咱們來介紹持久性
我想,任何用戶都必定不但願下述的這種狀況發生:李雷和韓梅梅都已經確認此次轉帳成功了。然而過了5分鐘,韓梅梅想用這充滿了感情的100元去買他想要的英語書的時候,卻發現錢不知去向了!?因而趕忙給支付寶打電話詢問,支付寶卻回答說:對不起您那帳戶的數據庫服務器重啓了,丟失了一部分的數據,您帳戶裏的那個錢正好在丟失範圍內,請節哀。
我想這時候應該有(bi….)的動機了吧:)htm

因而,這裏就須要作一個很基礎的保證:若是一個事務結束後,已經被其餘人看到了,那麼就不可以回退到事務以前的狀態了。
這就是事務的第三個重要的概念:持久性的含義blog

好了,咱們介紹了三個關鍵的概念,原子性A,一致性C,持久性D。下課~進程

可能有看過其餘數據庫書籍的人會問了:」等等,你這不對吧?事務不是四個特性麼?別忽悠咱們啊,咱們明天面試還得背這些概念呢,要不找不到工做啊~」

好好好,我立刻來介紹隔離性。。。

其實,我將隔離性從上面幾個屬性中剝離出來,是有我本身的考慮的,主要緣由是我我的認爲,隔離性從邏輯概念上不與上面介紹的ACD平級。爲何這麼說呢?個人理由是,若是要模擬現實中發生的各類操做,只須要保證ACD三個屬性,就可以完美的完成一次事務操做了,隔離性則明顯是多餘的。。

」那麼,既然多餘,去掉不就行了。。還留着他幹啥?不知道這個隔離性是最(biiiii…)複雜的概念麼,上次面試就由於沒說明白這貨因此面試被鄙視了呢!」

唉,這還真去不掉,由於去掉了,數據庫的事務就慢的受不了了。。因此數據庫開山的那批大牛也就不顧邏輯的清晰不清晰了,把這個概念加入了事務的四大要素。

從這件事,咱們也就能感覺到這個概念對性能的重要性了吧。。甚至能夠說,數據庫事務性能是否可以提高,關鍵就看你能接受哪一個隔離級別了呢!

咋樣?是否是對這個概念肅然起敬了?好,那麼咱們就來看看隔離性是個什麼東西。

首先,明確隔離性要解決的問題域,與上面爲了保證一次事務提交邏輯上的正確性不一樣的,隔離性主要解決的問題是性能,或者更直接點,就是儘量的下降受到鎖影響的事務進程的個數的。

而後,看他解決問題的方法:
在以前咱們提到,一致性要保證數據被其餘人看到的時候必須是一個完整的數據狀態,數據更新過程當中的中間狀態則不能被看到。
好了,大牛們剛剛說了限定條件,下面立馬給本身來了個響亮的自抽。。

隔離性的最低級別,就是讀未提交
什麼叫讀未提交呢?咱們來抄維基。。
讀未提交,可能出現髒讀,當一個事務試圖讀取另外一個還未提交的事務正在修改的某一行數據時,骯髒讀取(dirtyreads)就會發生。

簡單來講,就是一個事務,須要同時更新兩張表的數據,而另外一我的去讀這兩張表的數據的時候,可能可以讀到一張表的新值和另一張表的老值!
這明顯就違反了一致性不是:)

其實,從我上面舉出的例子,你就能感覺到,一致性和隔離性應該被一塊兒考慮,一致性描述的是理想的事務過程應該怎樣,而理想的事務由於鎖的範圍太大以致於性能難以接受,因此就使用隔離性的多個隔離級別來破壞一致性應該給出的保證,以換取更小的鎖範圍,從而獲取更高的性能。

在這一篇,我不會擴展隔離性這個概念,由於若是不聯繫實際的數據庫實現而死記硬背各類隔離級別的概念,我以爲太難理解這個概念了。

所以,我將在後面展開討論事務和分佈式事務的章節再來關注隔離性的四個級別的問題。在這裏,若是你回顧本篇的時候,若是能回想起原子,一致,持久這三個特性產生的緣由,而後又能理解到隔離性主要解決的問題域,以及從最低級別:讀未提交,到最高級別:可序列化,隔離性的本質就是一個鎖的範圍逐漸擴大,性能逐漸下降,但能提供更強級別的一致性保證的這麼一個特徵。那麼個人目標也就達到了。

隨着隔離性概要介紹的完結,數據庫系統概述這一章也就隨着這篇概述的結束而結束了,在本章,我寫做的主要目標就是,用盡量具象化的例子來對一個數據庫系統作了一個概要性的描述。
下面,我會在後面的章節開始深刻到分佈式存儲的一些重要的領域進行更深刻的探討。

enjoy~

相關文章
相關標籤/搜索