《MySQL實戰45講》讀後感 03|事務隔離:爲什麼你改了我還看不見

收穫到的知識點

  • 事務支持是在引擎層面實現的,但是並不是所有的引擎都支持事務,比如MySQL原生的MyISAM引擎就不支持事務,這也是MyISAM被 InnoDB取代的原因之一
  • 多個事務同時執行的時候,可能出現這3種情況:髒讀(dirty read)、不可重複讀(non-repeatable read)、幻讀(phanton read),爲了解決這些總是就有了“隔離級別”的概念
  • 隔離級別有哪些級別:讀未提交(read uncommitted)、讀已提交(read committed)、可重複讀(repeatable read)、可串行化(serializable)

隔離級別產生的效果

我們來看看在不同的隔離級別下,事務 A 會有哪些不同的返回結果,也就是圖裏面 V1、V2、V3 的返回值分別是什麼。
在這裏插入圖片描述
若隔離級別是“讀未提交”, 則 V1 的值就是 2。這時候事務 B 雖然還沒有提交,但是結果已經被 A 看到了。因此,V2、V3 也都是 2。
若隔離級別是“讀提交”,則 V1 是 1,V2 的值是 2。事務 B 的更新在提交後才能被 A 看到。所以, V3 的值也是 2。
若隔離級別是“可重複讀”,則 V1、V2 是 1,V3 是 2。之所以 V2 還是 1,遵循的就是這個要求:事務在執行期間看到的數據前後必須是一致的。
若隔離級別是“串行化”,則在事務 B 執行“將 1 改成 2”的時候,會被鎖住。直到事務 A 提交後,事務 B 纔可以繼續執行。所以從 A 的角度看, V1、V2 值是 1,V3 的值是 2。

隔離級別的實戰練習:

準備工作:

在這裏插入圖片描述

隔離級別不同那麼如何實現的:
在實現上,數據庫裏面會創建一個視圖,訪問的時候以視圖的邏輯結果爲準。在“可重複讀”隔離級別下,這個視圖是在事務啓動時創建的,整個事務存在期間都用這個視圖。在“讀提交”隔離級別下,這個視圖是在每個 SQL 語句開始執行的時候創建的。這裏需要注意的是,“讀未提交”隔離級別下直接返回記錄上的最新值,沒有視圖概念;而“串行化”隔離級別下直接用加鎖的方式來避免並行訪問。

事務的啓動方式:

MySQL 的事務啓動方式有以下幾種:
顯式啓動事務語句, begin 或 start transaction。配套的提交語句是 commit,回滾語句是 rollback。
set autocommit=0,這個命令會將這個線程的自動提交關掉。意味着如果你只執行一個 select 語句,這個事務就啓動了,而且並不會自動提交。這個事務持續存在直到你主動執行 commit 或 rollback 語句,或者斷開連接。

有些客戶端連接框架會默認連接成功後先執行一個 set autocommit=0 的命令。這就導致接下來的查詢都在事務中,如果是長連接,就導致了意外的長事務。
因此,我會建議你總是使用 set autocommit=1, 通過顯式語句的方式來啓動事務。

課堂問題

Q:你現在知道了系統裏面應該避免長事務,如果你是業務開發負責人同時也是數據庫負責人,你會有什麼方案來避免出現或者處理這種情況呢?
A:事前寫代碼環節,可以不用事務的地方就不要加事務,比如一些獨立的select操作,合理使用數據庫連接池dbpool(c3p0,dbcp,druid),在需要啓用事物的地方纔開啓事物,try{setautocommit(false)}finly{setautocommit(true)};事後增加db監控,定期就監控到的長事物進行review驗證其合理性。

順便分享一下林奇大師的課程,有興趣的可以看看

在這裏插入圖片描述

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