數據庫的臟讀、不可重復讀和幻讀區別


眾所周知MySQL從5.5.8開始,Innodb就是默認的存儲引擎,Innodb最大的特點是:支持事務、支持行級鎖。 既然支持事務,那么就會有處理並發事務帶來的問題:更新丟失、臟讀、不可重復讀、幻讀;相應的為了解決這四個問題, 就產生了事務隔離級別:未提交讀(Read uncommitted),已提交讀(Read committed),可重復讀(Repeatable read),可序列化(Serializable)。

 

事務的特性:

原子性:指處於同一個事務中的多條語句是不可分割的。即它對數據庫的修改要么全部執行,要么全部不執行

一致性:事務必須使數據庫從一個一致性狀態變換到另外一個一致性狀態。比如轉賬,轉賬前兩個賬戶余額之和為2k,轉賬之后也應該是2K。

隔離性:指多線程環境下,一個線程中的事務不能被其他線程中的事務打擾 持久性:事務一旦提交,就應該被永久保存起來。

持久性:事務一旦提交,就應該被永久保存起來。

 

1、概念說明:      

更新丟失:最后的更新覆蓋了其他事務之前的更新,而事務之間並不知道,發生更新丟失。更新丟失,可以完全避免,應用對訪問的數據加鎖即可。   

臟讀(針對未提交的數據):一個事務在更新一條記錄,未提交前,第二個事務讀到了第一個事務更新后的記錄,那么第二個事務就讀到了臟數據,會產生對第一個未提交 數據的依賴。一旦第一個事務回滾,那么第二個事務讀到的數據,將是錯誤的臟數據。   

不可重復讀(讀取數據本身的對比):一個事務在讀取某些數據后的一段時間后,再次讀取這個數據,發現其讀取出來的數據內容已經發生了改變,就是不可重復讀。   

幻讀(讀取結果集條數的對比):一個事務按相同的查詢條件查詢之前檢索過的數據,確發現檢索出來的結果集條數變多或者減少(由其他事務插入、刪除的),類似產生幻覺。

 

2、事務隔離級別:   

並發處理帶來的問題中,更新丟失可以完全避免,由應用對數據加鎖即可。臟讀、不可重讀度、幻讀,其實都是數據庫的一致性問題,必須由一定的事務隔離機制來解決。 其中一種方法是:不用加鎖,通過一定的機制生成一個數據請求時間點的一致性快照,並用這個快照來提供一個界別的一致性讀取。從用戶的角度看,好像是數據庫提偶拱了 統一數據的多個版本。這種技術叫做:數據庫多版本並發控制,MVCC 多版本數據庫。   

事務隔離的本質是使事務在一定程度上串行化執行,顯然和並發機制是矛盾的。數據庫的事務隔離越嚴格,並發負作用越小,代價越高(影響並發訪問了唄)。   

為了解決隔離和並大的矛盾,IOS SQL92規定了4個隔離級別。(隔離==串行)

大多數數據庫默認的事務隔離級別是 Read Committed,比如 SQL Server , Oracle。但 MySQL 的默認隔離級別是 Repeatable Read。

  舉例1:

臟讀(Read Uncommitted)
通俗的講,一個事務在處理過程中讀取了另外一個事務未提交的數據。(你都還沒提交,我就讀到了你剛操作的數據,萬一你回滾了怎么辦,你說這臟不臟。)
舉例(事務B未提交,事務A卻讀到了事務B未提交的數據)

3.2 不可重復讀(Non-repeatable Read)
通俗的講,一個事務范圍內,多次查詢某個數據,卻得到不同的結果。
與臟讀的區別:臟讀是讀到未提交的數據,而不可重復讀讀到的卻是已經提交的數據,但實際上是違反了事務的一致性原則。
舉例(事務B提交后,事務A卻讀到了事務B已提交的數據,導致事務A兩次讀到地數據不一致)

3.3 幻讀
在Repeatable Read隔離級別下,一個事務可能會遇到幻讀(Phantom Read)的問題。
事務A讀取與搜索條件相匹配的若干行。事務B以插入或刪除行等方式來修改事務A的結果集,然后再提交。
舉例(id主鍵唯一,事務A搜索id=10的數據,事務A搜索不到id=10的數據,然后事務B新增id=10的數據並提交,事務A更新id=10的數據卻成功,插入id=10卻失敗,現在搜索id=10也有記錄)

  舉例2:

  1. 臟讀的情況:對於兩個事務T1與T2,T1讀取了已經被T2更新但是還沒有提交的字段之后,若此時T2回滾,T1讀取的內容就是臨時並且無效的

  開啟兩個mysql客戶端,並創建一張測試表transaction

  

  更改默認隔離級別REPEATABLE READ為READ UNCOMMITTED,用於測試

SELECT @@tx_isolation; #查詢隔離級別
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; # 更改隔離級別

  

   兩個客戶端同時開啟事務,其中一個事務做UPDATE操作,另一個事務做SELECT

  

  若此時黑色背景的客戶端進行回滾,則白色背景的客戶端讀取的數據就是臨時並且無效的。即臟讀。

  2. 不可重復讀: 對於兩個事務T1和T2,T1讀取了一個字段,然后T2更新了該字段並提交之后,T1再次提取同一個字段,值便不相等了。

  

  重復讀取的結果不一致的情況發生。

  3. 幻讀: 對於兩個事務T1、T2,T1從表中讀取數據,然后T2進行了INSERT操作並提交,當T1'再次讀取的時候,結果不一致的情況發生。

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM