mysql幻影讀怎麼解決 MYSQL如何解決幻讀

2021-10-17 13:36:00 字數 2361 閱讀 8943

首先要了解下mysql資料庫的事務特徵之一隔離級別:

read uncommitted(未提交讀):

在readuncommitted級別,事務中的修改,即使沒有提交,對其他事務也都是可見的。事務可以讀取未提交的資料,這也被稱為髒讀(dirtyread)。這個級別會導致很多問題,從效能上來說,readuncommitted不會比其他的級別好太多,但卻缺乏其他級別的很多好處,除非真的有非常必要的理由,在實際應用中一般很少使用。

read committed( 提交讀)

大多數資料庫系統的預設隔離級別都是readcommitted(但mysql不是)。readcommitted滿足前面提到的隔離性的簡單定義:乙個事務開始時,只能「看見」已經提交的事務所做的修改。換句話說,乙個事務從開始直到提交之前,所做的任何修改對其他事務都是不可見的。這個級別有時候也叫做不可重複讀(nonrepeatableread),因為兩次執行同樣的查詢,可能會得到不一樣的結果。

repeatable read( 可重複讀)

repeatableread解決了髒讀的問題。該級別保證了在同乙個事務中多次讀取同樣記錄的結果是一致的。但是理論上,可重複讀隔離級別還是無法解決另外乙個幻讀(phantomread)的問題。所謂幻讀,指的是當某個事務在讀取某個範圍內的記錄時,另外乙個事務又在該範圍內插入了新的記錄,當之前的事務再次讀取該範圍的記錄時,會產生幻行(phantomrow)。innodb和xtradb儲存引擎通過多版本併發控制(mvcc,multiversionconcurrencycontrol)解決了幻讀的問題。本章稍後會做進一步的討論。可重複讀是mysql的預設事務隔離級別。

serializable(可序列化)

serializable是最高的隔離級別。它通過強制事務序列執行,避免了前面說的幻讀的問題。簡單來說,serializable會在讀取的每一行資料上都加鎖,所以可能導致大量的超時和鎖爭用的問題。實際應用中也很少用到這個隔離級別,只有在非常需要確保資料的一致性而且可以接受沒有併發的情況下,才考慮採用該級別。

第二部分

mvcc是如何解決幻讀的呢,來,

mysql的大多數事務型儲存引擎實現的都不是簡單的行級鎖。基於提公升併發效能的考慮,它們一般都同時實現了多版本併發控制(mvcc)。不僅是mysql,包括oracle、postgresql等其他資料庫系統也都實現了mvcc,但各自的實現機制不盡相同,因為mvcc沒有乙個統一的實現標準。

可以認為mvcc是行級鎖的乙個變種,但是它在很多情況下避免了加鎖操作,因此開銷更低。雖然實現機制有所不同,但大都實現了非阻塞的讀操作,寫操作也只鎖定必要的行。

mvcc的實現,是通過儲存資料在某個時間點的快照來實現的。也就是說,不管需要執行多長時間,每個事務看到的資料都是一致的。根據事務開始的時間不同,每個事務對同一張表,同一時刻看到的資料可能是不一樣的。如果之前沒有這方面的概念,這句話聽起來就有點迷惑。熟悉了以後會發現,這句話其實還是很容易理解的。

前面說到不同儲存引擎的mvcc實現是不同的,典型的有樂觀(optimistic)併發控制控制和悲觀(pessimistic)併發控制。

下面我們通過innodb的簡化版行為來說明mvcc是如何工作的。

innodb的mvcc,是通過在每行記錄後面儲存兩個隱藏的列來實現的。這兩個列,乙個儲存了行的建立時間,乙個儲存行的過期時間(或刪除時間)。當然儲存的並不是實際的時間值,而是系統版本號(systemversionnumber)。每開始乙個新的事務,系統版本號都會自動遞增。事務開始時刻的系統版本號會作為事務的版本號,用來和查詢到的每行記錄的版本號進行比較。下面看一下在repeatableread隔離級別下,mvcc具體是如何操作的。

select    innodb會根據以下兩個條件檢查每行記錄:innodb只查詢版本早於當前事務版本的資料行(也就是,行的系統版本號小於或等於事務的系統版本號),這樣可以確保事務讀取的行,要麼是在事務開始前已經存在的,要麼是事務自身插入或者修改過的。行的刪除版本要麼未定義,要麼大於當前事務版本號。這可以確保事務讀取到的行,在事務開始之前未被刪除。只有符合上述兩個條件的記錄,才能返回作為查詢結果。

insert    innodb為新插入的每一行儲存當前系統版本號作為行版本號。

delete    innodb為刪除的每一行儲存當前系統版本號作為行刪除標識。

update   innodb為插入一行新記錄,儲存當前系統版本號作為行版本號,同時儲存當前系統版本號到原來的行作為行刪除標識。儲存這兩個額外系統版本號,使大多數讀操作都可以不用加鎖。這樣設計使得讀資料操作很簡單,效能很好,並且也能保證只會讀取到符合標準的行。不足之處是每行記錄都需要額外的儲存空間,需要做更多的行檢查工作,以及一些額外的維護工作。mvcc只在repeatableread和readcommitted兩個隔離級別下工作。其他兩個隔離級別都和mvcc不相容(4),因為readuncommitted總是讀取最新的資料行,而不是符合當前事務版本的資料行。而serializable則會對所有讀取的行都加鎖。

MySQL談談InnoDB怎麼解決幻讀的

首先說結論,在rr的隔離級別下,innodb使用mvcc和next key locks解決幻讀,mvcc解決的是普通讀 快照讀 的幻讀,next key locks解決的是當前讀情況下的幻讀。事務a,先執行 update table set name hh where id 3 結果為 ok row...

mysql到底是怎麼解決幻讀的?

mysql到底是怎麼解決幻讀的?mvcc是什麼,怎麼實現的?先理解幾個概念 非鎖定的一致性讀 圖中左邊為非一致性讀部分 非一致性讀 在sql查詢的時候,如果發現記錄已經被加了x鎖,會轉而查詢當前記錄回滾段中最近的快照,讀快照不加鎖,非常快 mvcc 多版本控制 這裡的多版本就是指的回滾段的快照,用來...

MySQL 到底是怎麼解決幻讀的?

在一次事務裡面,多次查詢之後,結果集的個數不一致的情況叫做幻讀。而多出來或者少的哪一行被叫做幻行。在高併發資料庫系統中,需要保證事務與事務之間的隔離性,還有事務本身的一致性。如果你看到了這篇文章,那麼我會預設你了解了髒讀 不可重複讀與可重複讀。多數資料庫都實現了多版本併發控制,並且都是靠儲存資料快照...