對於數據庫中事務的隔離級別的理解

衆所周知,數據庫事務的隔離級別有四種:

read uncmmitted 讀未提交,事務中的修改,即使沒有提交,對其他事務也是可見的。

read commited 讀提交(也稱不可重複讀),一個事務開始直到提交之前,所做的任何修改對其他事務都是不可見的。

repeatable read 可重複讀,同一事務中,多次讀取同樣記錄的結果是一致的。

serializable 可串行化,強制事務串行執行,避免幻讀問題。

事務隔離級別和對應存在的問題如下圖:

使用MySQL語句來理解事務的隔離級別。

有一個員工表employee,定義如下圖,含三個字段id, name, salary。

一、讀未提交

0 alice工資每月5000,

1 老闆開始一個事務:將alice薪設置爲10000。

2 尚未提交事務時,alice查詢到自己的薪資是10000。

3 一會兒,老闆回滾了事務。此時Alice的薪資還是5000。可是Alice讀到了髒數據10000。

上面的事務執行update後,執行下面的語句,再執行上面事務中的回滾。

二、讀提交

讀提交,又稱不可重複讀,在該隔離級別下的同一個事務中,多次讀相同記錄,可能出現數據不一致。

開始事務,查詢alice的薪資,(另有人修改了alice的薪資),再次查詢alice的薪資,會發現兩次查詢得到的結果不一樣。詳情如下圖:

可以看到上圖事務中兩次讀取到的數據不一樣。

三、可重複讀

可重複讀解決了上面不可重複讀的問題。

其他事務的修改,對己事務不可見。在上圖事務兩次查詢中間,執行了下圖中的更新。可發現,上圖事務中兩次查詢的結果一致,可重複讀。

四、可串行化

圖中先開始執行的事務雖然沒有更新數據,但還沒結束呢。這時另一個事務要更新數據。因爲事務隔離級別是可串行化,強制事務串行執行,所以另一個事務就被阻塞了。長時間阻塞會超時退出:ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction。

另:還遺留一個問題,可重複讀隔離級別下如何復現幻讀現象?

現在再來看高性能MySQL書中的講解,是不是容易理解下圖了:)

參考鏈接:

如何編寫事務https://dev.mysql.com/doc/refman/5.7/en/commit.html

如何設置數據庫的隔離級別:https://dev.mysql.com/doc/refman/5.7/en/set-transaction.html

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