數據庫常用的隔離級別

數據庫常用的隔離級別


四大特性

任何支持事務的數據庫,都必然具備四大特性ACID:

  • 原子性(Atomicity):說的是一個事物內所有操作共同組成一個原子包,要麼全部成功,要麼全部失敗。這是最基本的特性,保證了因爲一些其他因素導致數據庫異常,或者宕機。
  • 一致性(Consistency):在基於原子性的前提下,保證雙方數據的一致性;因爲原子性保證的只是雙方的操作是一致的,但在操作存在事務與時延;一致性得保證的只會有前狀態和後狀態,絕不會出現中間態。
  • 隔離性(Isolation):基於原子性和一致性的前提下,事務的隔離,因爲事務是可以有多個原子包的形式併發執行,但是,每個事物互不干擾。
  • 持久性(Durability):當一個事務提交後,數據的狀態則永遠都改變。不能因爲提交後服務器宕機,而導致提交失效。

只有確保以上四點的數據庫,這樣才能確保事務(Transaction)的正確性。


事務隔離

事務隔離就是指:多個併發的事務同時訪問一個數據庫時,一個事務不應該被另一個事務所幹擾,每個併發的事務間要相互進行隔離。

沒有事務隔離所產生的問題

  • 髒讀:A查詢 B修改後未提交的的數據;當B回滾後,則A查詢的數據是無效的;
  • 不可重複讀:A在第一次查詢用戶甲的信息,B將用戶甲的信息修改並提交;A再次獲取甲的信息,A兩次獲取的信息不同則稱之爲“不可重複讀”;
  • 幻讀:類似不可重複讀,A查詢用戶數量,當B新增或刪除用戶,A再次獲取用戶的數量不同;則稱之爲“幻讀”。

PS:“不可重複讀”與“幻讀”區別在於,不可重複讀強調的是數據信息的改變,而幻讀強調數據數量上的改變。


事務隔離級別

爲了防止以上情況所產生的髒讀不可重複讀幻讀等情況,我們就需要根據實際情來設定數據的事務隔離級別;

  • 讀未提交(Read Uncommitted)最低級別,任何情況都無法保證。就是可以讀到未提交的內容,在這種隔離級別下,查詢是不會加鎖的,也由於查詢的不加鎖,所以這種隔離級別的一致性是最差的,可能會產生“髒讀”、“不可重複讀”、“幻讀”。
  • 讀提交(Read Committed)可避免髒讀的發生。就是隻能讀到已經提交了的內容。
  • 可重複讀(Repeated Read)可避免髒讀、不可重複讀的發生。當事務啓動時,就不允許進行“修改操作(Update)”了,而“不可重複讀”恰恰是因爲兩次讀取之間進行了數據的修改,因此,“可重複讀”能夠有效的避免“不可重複讀”,但卻避免不了“幻讀”,因爲幻讀是由於“插入或者刪除操作(Insert or Delete)”而產生的。
  • 串行化(Serializable)可避免髒讀、不可重複讀、幻讀的發生。這是數據庫最高的隔離級別,這種級別下,事務“串行化順序執行”,也就是一個一個排隊執行。這種級別下,“髒讀”、“不可重複讀”、“幻讀”都可以被避免,但是執行效率奇差,性能開銷也最大,所以基本沒人會用。

以上四種隔離級別,串行化(Serializable) 的級別最高,讀未提交(Read uncommitted) 的級別最低,級別越高,效率越低
串行化(Serializable)就是以鎖的方式使其他線程只能在鎖外面等待;

MySQL支持上面四種隔離級別,默認的隔離級別是可重複讀(Repeatable read)

Oracle數據庫只支持 串行化(Serializable)讀已提交 (Read committed) ,默認是讀已提交(Read committed);


總結

爲什麼會出現“髒讀”? 因爲“select”操作沒有規矩。

爲什麼會出現“不可重複讀”? 因爲“update”操作沒有規矩。

爲什麼會出現“幻讀”? 因爲“insert”和“delete”操作沒有規矩。

“讀未提(Read Uncommitted)”能預防啥? 啥都預防不了。

“讀提交(Read Committed)”能預防啥? 使用“快照讀(Snapshot Read)”,避免“髒讀”,但是可能出現“不可重複讀”和“幻讀”。

“可重複讀(Repeated Red)”能預防啥? 使用“快照讀(Snapshot Read)”,鎖住被讀取記錄,避免出現“髒讀”、“不可重複讀”,但是可能出現“幻讀”。

“串行化(Serializable)”能預防啥? 排排坐,吃果果,有效避免“髒讀”、“不可重複讀”、“幻讀”,不過效果誰用誰知道。

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