什麼是事務的一致性?一致性和原子性的區別是什麼?

(PS:黃色字體爲二次修改的內容)

關於事務的一致性,《數據庫系統概念》中是這樣描述的

第二段說的三個特性是指原子性、隔離性、持久性。

就算這樣,相信大家也是懵懵的,我也是,所以纔會寫下這篇博客。

看到別的博客說,一致性是事務的最終目的,原子性、隔離性、持久性都是爲了實現一致性。

在這裏,我打算驗證一番。

怎麼驗證呢?

假設,這個事務系統如果是由我們來設計的話。

首先,場景是這樣的,小范轉100塊錢給小黃,那麼這個事務系統必須要保證小范扣了100塊錢,而且小黃也必須要加了100塊錢。

這個我們要怎麼保證呢?

有了,我們可以先用一本本子記下來,小范扣100塊錢,小黃加100塊錢,然後,我們再根據本子上寫的,順序執行,這樣的話,小范或者小黃就沒法耍賴了。

OK,那麼我們現在就開幹,把這個事務系統開發出來,下面是僞代碼:

//事務系統
abstract class transaction{

    void transaction(){

        /* todo:將所有操作寫進日誌
         * args: 事務名稱, 事務操作, 事務寫入狀態(0 未寫完 1已寫完)
         */
        setLog("小范轉100塊錢給小黃", "小范-100", 0);
        setLog("小范轉100塊錢給小黃", "小黃+100", 1);

        //獲取日誌
        Log logs = getLog("小范轉100塊錢給小黃");

        //解析日誌,獲取操作事件
        Event events = parseLog(logs);
        
        //執行操作並回寫日誌狀態標記該事務已完成
        doEvent(events, logs);

    }

}

OK,系統開發出來了,我們把它應用上去跑起來試下。

但是,可能是因爲計算機內存不夠,系統跑到一半,閃退了。。。

也就是doEvent的時候,小范扣了100塊錢,這個時候閃退了。。。

上數據庫一看,完了,小范已經扣了100,但是小黃並沒有增加100,事務也沒有執行下去。

所以我們這個事務系統是有問題的,我們的事務系統,應該要保證小范扣100,而且小黃也要加100,我們姑且稱這種狀態爲一致性,因爲我們要保證這兩個操作對數據而言是一致的嘛。

從目前來看,我們這個事務系統,沒有完全實現一致性,那如果發生了這種狀況,系統閃退停機等等異常情況,我們該怎麼處理,才能保證一致性呢?

有了,我們可以在日誌中多加一個狀態,用來標記該操作有沒有執行,然後用一個定時器,每隔幾秒找出日誌中沒有完成的事務,把它執行完,這樣一來,就能保證小范扣了100,小黃加了100了,哪怕中途停機了,也能用定時器把事務執行完。

就這樣測試了十來次,結果跟操作都一致,確實能保證一致性了,就正式給用上生產環境了。

可是纔不到一天,就出問題了,怎麼呢?有個業務,小張向老李轉賬300元,可是小張的賬戶上只有298,該死的初級程序員又沒有對小張的金額作校驗,直接就給執行了。

這下小張的賬戶餘額變成了-2,老李的賬戶變成了300。鬧了個大笑話。

這雖然主要責任不在我們開發的事務系統,但是,我們也要做處理,也就是在小張的餘額做加減的時候,減成了負數,這個時候程序應該需要拋出異常的,不能讓程序再執行下去了,所以,這就需要我們的事務系統,可以在執行到一半的時候,回滾到初始狀態。

也就是說,如果同一個事務中,有操作ABC三個順序操作,操作A成功了,操作B失敗了,那這操作C還要執行嗎?當然不能,這種情況,B失敗了,我們就只能把A給回滾到操作之前。

這樣一來,我們這個事務系統就是,要麼事務都完成,要麼事務都不完成,我們姑且就把這個叫做原子性吧。

增加了原子性的功能後,事務系統又開始跑了。

過了幾天,又出問題了,怎麼呢?原來啊,小范有300塊錢,小張向小范轉了500塊錢,事務還沒操作完呢,小劉又給小范轉了300塊錢,這樣一來,問題就來了,小張給小范轉500,本應該事務結束的時候小范有800塊錢,可是小劉又給小范轉了300,還是用小范原有的300去增加的,這樣一來,小劉的事務結束,小范就有600塊錢,小張的事務執行完,把800寫回給小范,接着,小劉的事務也執行完,把600寫回給小范,導致最終小范賬上只有600塊錢,小張的500被吞了。

這樣,數據完全混亂了。問題出在哪呢?在於小張事務執行的時候,讀取到小范有300,事務沒完,小劉也讀取到小范有300,這樣就錯亂了,我們應該要讓小張在轉賬的時候,小劉要等小張轉完了,才能轉。這樣,才能解決掉數據混亂的問題,我們,姑且把這個叫做隔離性。

隔離性修復完之後,項目又開始運作了,事務系統運行了很長一段時間,也沒有出現問題。

到這裏,驗證就結束了,上面寫日誌的行爲其實就是事務的持久性,也可以看到,上面出現的隔離性、原子性、持久性,也都是爲了徹底實現一致性而產生的。

所以,總的來說,一致性是一個比較籠統的概念,是事務的基礎,一致性和原子性的區別就是,原子性強調的是操作的完整,要麼都成功、要麼都不成功,而一致性包含的比較多,數據的一致性啊等等。

不過其實,我覺得一致性不應該跟原子性、隔離性、持久性放在一起,因爲這三個都是爲了實現一致性,如果有大佬知道,麻煩跟我說下原因。

到這,本文就結束了,寫的真的不是很好,以後,要是我對事務一致性、原子性有了新的理解,我會再回來修改的,也歡迎各位大佬留言或者私聊我,給我寫關於一致性的啓發。

知乎上有個回答也是寫的蠻好的,大家可以看看,https://www.zhihu.com/question/30272728

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章