資料庫事務的三個元問題
✏️ 編者按:
在《一文解析資料庫的三生三世》這篇文章中,我們站在歷史的角度認識了資料庫的「前世今生」。文中提到線上事務處理等關鍵場景,那究竟什麼是資料庫的事務?為什麼資料庫需要支援事務?為了實現資料庫事務,各種資料庫是如何設計的?讓我們一起來看看資料庫事務的三個元問題吧!
首發|AI 前線
作者|Zilliz
什麼是資料庫事務
事務,就是用來保證資料操作符合業務邏輯要求而實現的一系列功能。換句話說,如果資料庫不支援事務,上層業務系統的程式設計師就需要自己寫程式碼,以保證相關資料處理邏輯的正確性。舉個例子,資料庫最開始普及就是在金融業,銀行的存取款場景就是一個最典型的 OLTP 資料庫場景,而事務就是用來保證類似場景的業務邏輯正確性的。

原子性:如果你要給家人轉賬,必須在你的賬戶里扣掉 100 塊,在家人賬戶里加上 100 塊,這兩筆操作需要一起完成,業務邏輯才是正確的。但是程式在做修改時,肯定會有先後順序,試想一下程式扣了你的錢,這個時候程式崩潰了,家人賬戶的錢沒有加上,那這 100 塊是不是消失了?你是不是要發瘋?那麼,就把這兩筆操作放進一個事務裡,通過原子性保證,這兩筆操作要麼都成功,要麼都失敗。這樣才能保證業務邏輯的正確性。
一致性:有很多文章講過一致性,但是很多人會把一致性跟原子性混在一起說。事務的一致性指的是,每一個事務必須保證執行之後所有庫內的規則依舊成立,比如內外來鍵、constraint、觸發器等。舉例來說,你在儲蓄卡里有 100 元,理財賬戶裡有 100 元,基金賬戶有 100 元,那麼你在資產總和裡會看到 300 元,這 300 元必須是三個賬戶餘額加在一起得到的。你從儲蓄卡里轉出去了 100 元給家人,那麼可以在資料庫上建立觸發器,當儲蓄卡餘額賬戶減 100 元的同時,把資產總和也同步減去 100 元,不然就會出現邏輯上的錯誤。你已經轉走了 100 元儲蓄卡餘額,實際資產總和應該是 200 元,若還是 300 元,資料庫狀態就不一致了。因此實現事務的時候,必須要保證相關聯的觸發器以及其他內部規則都執行成功,事務才算執行成功。如果在減去資產總額時出錯,資料庫就會進入不一致的狀態,那麼這筆轉帳交易也不能成功。
那麼一致性跟原子性的區別到底在哪裡呢?原子性是指多個使用者指令之間必須作為一個整體完成或失敗,而一致性更多是資料庫內的相關資料規則同時完成或失敗。
永續性:事務只要提交了,對資料庫的修改就會儲存下來不會丟了。簡單來說,只要提交了,資料庫就算崩潰了,重啟之後你剛存的 100 塊依然在你的賬戶裡。
隔離性:每個事務相對於其他的事務有一定獨立性、不能互相影響,因為資料庫需要支援併發的操作來提高效率。在併發操作時,一定要通過操作之間的隔離來保證業務邏輯的正確性。比如,你轉帳 100 塊給家人,一系列操作的最後一步可能是輸入驗證碼,這個時候轉帳還沒有完成,但是在資料庫裡,你的賬戶對應的記錄中已經減去 100 塊,家人賬戶也加了 100 塊,就等著驗證碼輸入以後,事務提交,完成操作。那麼,這個時候,家人通過手機銀行能夠查到這 100 塊麼?你的答案可能是不能,因為你的轉帳操作還沒有提交,事務還沒有完成,那麼資料庫就應該保證這兩個併發操作之間具有一定的隔離性,這樣才符合業務邏輯。
到底應該隔離到什麼程度呢?隔離性又分為 4 個等級:由低到高依次為 Read uncommitted(讀未提交)、Read committed(讀提交)、Repeatable read(可重複讀取)、Serializable(序列化),這四個級別可以逐個解決髒讀、不可重複讀、幻象讀這幾類問題。
怎麼理解不同的隔離等級呢?首先要理解併發操作,併發操作就是指有不同的使用者同時對一個數據進行讀、寫操作,那麼在這個過程中,每個使用者應該看到什麼資料才能保證業務邏輯的正確性呢?
如果是前面存取款的場景,我看到的是已經存進來的錢,也就是必須是已經提交的事務。而 12306 刷火車票,你可以看到有 10 張餘票,但是在下單的時候告訴你票賣完了,因為同時有 10 個使用者把票買掉了,你需要重新刷餘票。這個也是可以接受的。也就是說我可以讀到一些虛假的餘票,在業務上也沒有什麼問題。那麼在設計這兩個不同系統時,就可以選擇不同的事務隔離級別來實現不同的併發效果。不同的隔離等級就是在系統的併發性和資料邏輯的嚴謹性之間做出的平衡。
資料庫如何實現事務
MVCC 實現原理
所謂 MVCC,就是資料庫中的同一查詢根據相關事務執行的先後順序以及隔離級別的不同,可能會存在不同版本的結果,通過這樣的手段來保證大部分查詢操作不會被修改操作阻塞並保證資料邏輯的正確性。簡單來說就是,用儲存空間來交換併發能力。
(圖片來自網路,侵刪)
首先,Postgres 裡的每一個事務都有編號,這裡可以簡單理解為時間順序編號,編號越大的事務發生越晚。然後,資料庫裡的每一行記錄都會儲存建立這條記錄的事務號(Cre),也會在記錄刪除時儲存刪除這條記錄的事務號(Exp),換句話說,只要 Exp 這裡一列裡記錄了事務編號,就說明這條記錄被刪除了。那麼一個事務應該能看見哪些記錄呢?Postgres 裡每一個事務都會儲存一個當前系統的事務快照(Snapshot),這個快照裡會儲存事務建立時當前系統的最高(最晚)事務編號,以及目前還在進行中的事務編號。在如上圖所示的一個事務的快照裡,最高事務編號為 100,目前正在進行的事務有 25、50 和 75。對應左邊資料記錄,這 6 行資料的可見性就如同標註的一般:
-
第一行,Cre 30,沒有刪除,在 100 這個時間點,應該能看到。 -
第二行,Cre 50,沒有刪除,但是 50 這個事務還沒有提交,正在進行中,所以看不見。 -
第三行,Cre 110,沒有刪除,但是 100 這個時間點 110 事務還沒有發生,所以看不見。 -
第四行,Cre 30,Exp 80,在 80 的時候資料被刪掉了,所以看不見。 -
第五行,Cre 30,Exp 75,在 30 的時候被建立,75 時候被刪掉了,但是 75 這個事務在 100 的時候還沒有提交,這條記錄在 100 的時候還沒有刪掉,所以看得見。 -
第六行,Cre30,Exp 110,在 30 的時被建立,110 時候被刪掉,但是在 100 時候,110 還沒有發生,所以看得見。

本文分享自微信公眾號 - ZILLIZ(Zilliztech)。
如有侵權,請聯絡 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。
「其他文章」
- Lion : 超越 AdamW 的優化演算法
- ChatGPT 不是黑魔法,“替代搜尋引擎”言之尚早
- 36氪首發|推出全託管雲服務產品Zilliz Cloud,向量資料庫公司「Zilliz」完成6000萬美元B 輪融資
- Deep Dive 7:Milvus 2.0 質量保障系統詳解
- Milvus 向量資料庫如何實現屬性過濾
- 短視訊如何有效去重?vivo 短視訊分享去重實踐
- AI 收藏夾 Vol.004:虛擬愛豆出道!
- 【Zilliz專場】力扣第 271 場周賽覆盤
- 資料庫事務的三個元問題
- 從使用者到開發者,日本獨角獸 SmartNews 的社群二三事
- AI 收藏夾 Vol.002:被 AI 阻止的又一次自殺
- AI 收藏夾 Vol.003:AI 能聽懂陰陽怪氣嗎?
- 一文解析資料庫的三生三世
- FastAPI or Flask?從使用者出發,才是王道
- 畢業之後,開源給了我第一份工作
- 活用向量資料庫,普通散戶也能找到潛力股!
- 系統召回太慢?上 Milvus × PaddleRec 雙劍合璧大法!
- 13 種高維向量檢索演算法全解析!資料庫頂會 VLDB 2021 論文作者乾貨分享
- 千萬量級圖片視訊快速檢索,輕鬆配置設計師的靈感挖掘神器
- 深度 | 資料大變革,向量資料庫大牛揭祕設計理念