mysql是如何解決臟讀、不可重復讀、幻讀


數據庫的兩種讀,每種讀讀的數據版本不一樣,所以也稱為MVCC,即多版本並發控制

  a) 快照讀 

  select * from where xxx  這種形式的都是快照讀。

  b) 當前讀

  update , insert ,delete ,select xx from xx for update ,  in share mode 都是當前讀

  當前讀會等待,不會返回數據的歷史版本

 

 一. 不可重復讀與幻讀的區別:

 從總的結果來看,   似乎兩者都表現為兩次讀取的結果不一致.


但如果你從控制的角度來看,   兩者的區別就比較大
對與不可重復讀來說,   只需要鎖住滿足條件的記錄,主要針對是update和delete
幻讀,   要鎖住滿足條件及其相近的記錄,針對的是insert

 

####不可重復讀和幻讀的區別####
很多人容易搞混不可重復讀和幻讀,確實這兩者有些相似。但不可重復讀重點在於update和delete,而幻讀的重點在於insert。

如果使用鎖機制來實現這兩種隔離級別,在可重復讀中,該sql第一次讀取到數據后,就將這些數據加鎖,其它事務無法修改這些數據,就可以實現可重復 讀了。但這種方法卻無法鎖住insert的數據,所以當事務A先前讀取了數據,或者修改了全部數據,事務B還是可以insert數據提交,這時事務A就會 發現莫名其妙多了一條之前沒有的數據,這就是幻讀,不能通過行鎖來避免。需要Serializable隔離級別 ,讀用讀鎖,寫用寫鎖,讀鎖和寫鎖互斥,這么做可以有效的避免幻讀、不可重復讀、臟讀等問題,但會極大的降低數據庫的並發能力。

所以說不可重復讀和幻讀最大的區別,就在於如何通過鎖機制來解決他們產生的問題。

上文說的,是使用悲觀鎖機制來處理這兩種問題,但是MySQL、ORACLE、PostgreSQL等成熟的數據庫,出於性能考慮,都是使用了以樂觀鎖為理論基礎的MVCC(多版本並發控制)來避免這兩種問題。

####悲觀鎖和樂觀鎖####

  • 悲觀鎖

正如其名,它指的是對數據被外界(包括本系統當前的其他事務,以及來自外部系統的事務處理)修改持保守態度,因此,在整個數據處理過程中,將數據處 於鎖定狀態。悲觀鎖的實現,往往依靠數據庫提供的鎖機制(也只有數據庫層提供的鎖機制才能真正保證數據訪問的排他性,否則,即使在本系統中實現了加鎖機 制,也無法保證外部系統不會修改數據)。

在悲觀鎖的情況下,為了保證事務的隔離性,就需要一致性鎖定讀。讀取數據時給加鎖,其它事務無法修改這些數據。修改刪除數據時也要加鎖,其它事務無法讀取這些數據。

  • 樂觀鎖

相對悲觀鎖而言,樂觀鎖機制采取了更加寬松的加鎖機制。悲觀鎖大多數情況下依靠數據庫的鎖機制實現,以保證操作最大程度的獨占性。但隨之而來的就是數據庫性能的大量開銷,特別是對長事務而言,這樣的開銷往往無法承受。

而樂觀鎖機制在一定程度上解決了這個問題。樂觀鎖,大多是基於數據版本( Version )記錄機制實現。何謂數據版本?即為數據增加一個版本標識,在基於數據庫表的版本解決方案中,一般是通過為數據庫表增加一個 “version” 字段來實現。讀取出數據時,將此版本號一同讀出,之后更新時,對此版本號加一。此時,將提交數據的版本數據與數據庫表對應記錄的當前版本信息進行比對,如 果提交的數據版本號大於數據庫表當前版本號,則予以更新,否則認為是過期數據。

要說明的是,MVCC的實現沒有固定的規范,每個數據庫都會有不同的實現方式,這里討論的是InnoDB的MVCC。

 

參考:

  https://www.cnblogs.com/hansc-blog/p/9358524.html

  https://www.cnblogs.com/itcomputer/articles/5133254.html

  https://www.cnblogs.com/gotojava/p/13739511.html


免責聲明!

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



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