More  

小編的世界 優質文選 資料

「MySQL」事務隔離級別簡說


2020年9月06日 - 資料小編 java架構筆記 
   

架構師

A: Atomicity 原子性

事務是一個最小的執行單位,事務裏面的SQL要麼全執行,要麼全部不執行

以轉賬場景為例。A轉賬給B,則對應A扣錢的SQL,與B加錢的SQL。如果不能保證兩條SQL同時執行成功或失敗,那麼就有可能A錢扣了,但是B沒有收到錢。

C:Consistent 隔離性

一致性是指事務使得應用系統從一個正確的狀態到另一個正確的狀態。

知乎上面一個高贊回答的很特別,原子性、隔離性、持久性是數據庫事務的基本特征,而一致性是由AID這三個特征來保證的。

如果A有100元,轉賬給B120元,A的錢不足扣除,假如你給金額這一列設置了不能小於0的約束,那麼在事務執行的時候監測到約束沒被滿足,就會回滾,這時可以說事務保證了一致性。

同樣的,如果你沒有添加約束,而是在業務層做了校驗,並做了回滾,那麼也可以說事務保證了一致性。

那如果數據庫和業務層都沒有做約束呢,A的錢不就變為負數了嗎?這實際上也是保證了一致性,因為執行前後並沒有破壞任何約束,它的狀態一直都是正確的。

I:Isolate 隔離性

將事務與另一個事務隔離開

如果一個事務正在操作的數據被另一個事務修改或刪除了,最後的執行結果可能無法達到預期。

D:Durable 持久性

事務完成了對數據的修改之後,修改的結果是永久性生效的

事務並發帶來的問題

髒讀

最容易理解。另一個事務修改了數據,但尚未提交,而本事務中的SELECT會讀到這些未被提交的數據。

假如,中午去食堂打飯吃,看到一個座位被同學小Q占上了,就認為這個座位被占去了,就轉身去找其他的座位。不料,這個同學小Q起身走了。事實:該同學小Q只是臨時坐了一小下,並未“提交”。

不重複讀

同樣是兩個事務在操作同一數據,如果在事務開始時讀了某數據,這時候另一個事務修改了這條數據,等事務再去讀這條數據的時候發現已經變了,先後兩次讀到的數據結果不一致,這就是沒辦法重複讀一條數據。

假如,中午去食堂打飯吃,看到一個座位是空的,便屁顛屁顛的去打飯,回來後卻發現這個座位卻被同學小Q占去了。

幻讀

事務一開始按某個查詢條件沒查出任何數據,結果因為另一個事務的影響,再去查時卻查到了數據,這種就像產生幻覺了一樣,被稱作幻讀。

假如,中午去食堂打飯吃,看到一個座位是空的,便屁顛屁顛的去打飯,回來後,發現這些座位都還是空的(重複讀),竊喜。走到跟前剛准備坐下時,卻驚現一個恐龍妹,嚴重影響食欲。仿佛之前看到的空座位是“幻影”一樣。

事務的四種隔離級別

MySQL InnoDB事務的隔離級別有四級,默認是“可重複讀”(REPEATABLE READ)。

未提交讀(READ UNCOMMITTED)

讀未提交其實就是事務沒提交就可以讀,很顯然這種隔離級別會導致讀到別的還沒提交的數據,一旦基於讀到的數據做了進一步處理,而另一個事務最終回滾了操作,那麼數據就會錯亂,而且很難追蹤。總的來說說,讀未提交級別會導致髒讀

另一個事務修改了數據,但尚未提交,而本事務中的SELECT會讀到這些未被提交的數據(髒讀)。

提交讀(READ COMMITTED)

務提交後才能讀,假設你拿著銀行卡去消費,付錢之前你看到卡裏有2000元,這個時候你老婆在淘寶購物,趕在你前面完成了支付,這個時候你再支付的時候就提示餘額不足,但是分明你看到卡裏的錢是夠的啊。

這就是兩個事務在執行時,事務A一開始讀取了卡裏有2000元,這個時候事務B把卡裏的錢花完了,事務A最終再確認餘額的時候發現卡裏已經沒有錢了。很顯然,讀提交能解決髒讀問題,但是解決不了不可重複讀。

本事務讀取到的是最新的數據(其他事務提交後的)。問題是,在同一個事務裏,前後兩次相同的SELECT會讀到不同的結果(不重複讀)。

(默認)可重複讀(REPEATABLE READ)

解決不可重複讀問題,事務A一旦開始執行,無論事務B怎麼改數據,事務A永遠讀到的就是它剛開始讀的值。那麼問題就來了,假設事務B把id為1的數據改成了2,事務A並不知道id發生了變化,當事務A新增數據的時候卻發現為2的id已經存在了,這就是幻讀。

在同一個事務裏,SELECT的結果是事務開始時時間點的狀態,因此,同樣的SELECT操作讀到的結果會是一致的。但是,會有幻讀現象(幻讀)。

串行化(SERIALIZABLE)

所有的事務串起來一個個執行,因為沒有並發的場景出現了,什麼幻讀、髒讀、不可重複讀統統都不存在的。但是同樣的,基本並發能力會非常差。

讀操作會隱式獲取共享鎖,可以保證不同事務間的互斥。

  大家在看