數據庫事務 和 數據庫隔離級別

起因

有一天同事問我,晨哥晨哥,什麼是數據庫的隔離級別,我,額,稍等,冒汗,以前看過,現在忘了。
有時間寫一篇,下次再忘了還能看看。主要是自己看,順便滿足一下自己寫作的慾望,如果你不小心看到了,證明咱倆有緣分,別因爲我寫的不好噴我。

什麼是事務

你以爲第一件事是介紹數據庫隔離級別的定義嗎,

錯,

我們要先了解爲什麼有數據庫的隔離級別。

我們瞭解一件新知識的時候先要明白它是解決什麼問題的,數據庫隔離級別解決的是事務併發的問題。

那麼問題就來了,什麼是事務。

數據庫事務的概念比較簡單,不考試的情況下用口語表達就是幾個事件要麼一起生效,要麼一起失效
當然這個事件是數據庫的事件,生活中的事兒不要硬往上套。😄,笑臉,手動滑稽。

不鬧了,說正經的。正經臉。

併發事務的問題

事務併發會出現什麼問題,這還不簡單,兩個覆蓋問題,三個查詢問題

這就有意思了,什麼叫兩個覆蓋,三個查詢。

咱們以最經典的銀行卡餘額爲例。 假設有一張表,裏面就一個字段 money , 咱來看一下併發事務的問題。

money
1000

第一種覆蓋,因爲回滾覆蓋

時間點 事務A 事務B
T1 開啓事務 開啓事務
T2 讀到 1000 讀到 1000
T3 給賬號 + 500
T4 賬號餘額 1500
T5 提交事務
T6 給賬號 -500
T7 賬號餘額 500
T8 回滾事務
T9 賬號變 1000

最後丟失了事務 B 提交的記錄。

第二種覆蓋,因爲提交覆蓋

時間點 事務A 事務B
T1 開啓事務 開啓事務
T2 讀到 1000 讀到 1000
T3 給賬號 + 500
T4 賬號餘額 1500
T5 提交事務
T6 給賬號 -500
T7 賬號餘額 500
T8 提交事務
T9 賬號變 500

這是因爲提交覆蓋了 B 提交的事務。

第一種查詢,查詢到未提交的數據

時間點 事務A 事務B
T1 開啓事務 開啓事務
T2 讀到 1000
T3 給賬號 + 500
T4 賬號餘額 1500
T5 查詢到賬戶餘額 1500(髒讀)
T6 再給賬戶 +100 回滾事務
T7 賬號餘額 1600
T8 提交事務
T9 賬號變 1600

因此,讀到未提交的數據,也叫髒讀。

第二種查詢,查詢到已提交的數據

時間點 事務A 事務B
T1 開啓事務 開啓事務
T2 讀到 1000 讀到 1000
T3 給賬號 + 500
T4 賬號餘額 1500
T5 提交事務
T6 又讀一次,變 1500 了
T7 讀兩次效果不一樣

這種讀兩次效果不一樣的,也叫不可重複讀。

第三種查詢,查詢到新插入的數據

時間點 事務A 事務B
T1 開啓事務 開啓事務
T2 sum() 一下值是 1000
T3 插入一條新的 1000 的記錄
T4 提交事務
T5 再 sum() 一下值變成 2000 了

這種奇幻的效果就叫做幻讀。

數據庫隔離級別

既然事務併發會有這麼多的問題,那我們設計系統的時候總得有所取捨,到底哪些現象是和合理的,哪些現象是不合理的要避免的。

數據庫設計也是一樣,這些問題有些是不合理一定要避免的,有些呢,在業務場景中是合理的,不能一棍子打死。

那到底哪些場景下是合理的哪些是不合理的,數據庫把它設計成了一個可選項,就叫數據庫隔離級別,供開發人員選擇。

serializable (串行,建議記英文,中文表達不好)

所有事務操作都是串行的,一個事務執行完才執行下一下,這樣肯定不會用問題,當然效率也是最慢。

repeatable read (可重複讀)

就是讀不到別的事務的對記錄的更新【包括已提交和未提交】,能讀到已經提交的插入。InnoDB 存儲引擎通過多版本併發控制,MVCC 解決了幻讀的問題。

read committed (讀已提交)

就是能讀到別的事務對記錄的更新,也能讀到已插入的記錄

read uncommited (讀未提交)(也叫髒讀)

可以看到其他事務未提交的更新,插入也能看到。

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