首先說結論,在rr的隔離級別下,innodb使用mvcc和next-key locks解決幻讀,mvcc解決的是普通讀(快照讀)的幻讀,next-key locks解決的是當前讀情況下的幻讀。讀取歷史資料的方式,我們叫它快照讀 (snapshot read),而讀取資料庫當前版本資料的方式,叫當前讀 (current read)。
所謂當前讀,指的是加鎖的select(s或者x), update, delete等語句。在rr的事務隔離級別下,資料庫會使用next-key locks來鎖住本條記錄以及索引區間。
比如:在rr的情況下,假設使用的是當前讀,加鎖了的讀
select * from table where id>3 鎖住的就是id=3這條記錄以及id>3這個區間範圍,鎖住索引記錄之間的範圍,避免範圍間插入記錄,以避免產生幻影行記錄。
因為普通讀是不會加鎖的讀,故不會有next-key locks的使用,解決幻讀的手段是mvcc
mvcc會給每行元組加一些輔助字段,記錄建立版本號和刪除版本號。
而每乙個事務在啟動的時候,都有乙個唯一的遞增的版本號。每開啟乙個新事務,事務的版本號就會遞增。
預設的隔離級別(repeatable read)下,增刪查改變成了這樣:
關鍵點是:讀取的話,必須同時滿足兩個條件的
在rc的模式下,mvcc解決不了幻讀和不可重複讀,因為每次讀都會讀它自己重新整理的快照版本,簡單來說就是另乙個事務提交,他就重新整理一次,去讀最新的
在rr模型,我們雖然避免了幻讀,但是存在乙個問題,我們得到的資料不是資料中實時的資料,如果是對實時資料比較敏感的業務,這是不現實的。
事務的隔離級別實際上都是定義了當前讀的級別,mysql為了減少鎖處理(包括等待其它鎖)的時間,提公升併發能力,引入了快照讀的概念,使得select不用加鎖。而update、insert這些「當前讀」,就需要另外的模組來解決了。
比如,我們有以下的訂單業務場景,我們隊乙個商品下單的操作,我們得首先檢查這個訂單的數量還剩多少,然後下單。
假設這個時候數量只有1,我們下單也是只有1.如果在併發的情況下,事務1查詢到還有一單準備下單,但是這個時候事務2已經提交了。訂單變成0.這個事務1在執行update,就會造成事故。
參考:
InnoDB怎麼解決幻讀的?
首先說結論,在rr的隔離級別下,innodb使用mvcc和next key locks解決幻讀,mvcc解決的是普通讀 快照讀 的幻讀,next key locks解決的是當前讀情況下的幻讀。事務a,先執行 update table set name hh where id 3 結果為 ok row...
Mysql MVCC原理和幻讀解決
reference reference 快照讀 顧名思義,就是讀取的是快照資料,不加鎖的普通select都是快照讀 當前讀 就是讀取最新資料,而不是歷史資料,或者說不是快照資料,是加鎖的select,或者對資料進行正刪改都會進行當前讀。實現原理主要是版本鏈。undo日誌 readview來實現的。i...
InnoDB的MVCC如何解決幻讀
innodb預設的隔離級別是rr 可重複讀 可以解決髒讀和不可重複讀,但是不能解決幻讀問題。什麼是幻讀?事務a讀取了乙個範圍內的資料,此時事務b在該範圍內插入了一條資料,並立馬提交了事務,此時事務a再次讀取這個範圍的資料時,發現多了一條,就好像幻覺一樣。什麼是mvcc?多版本併發控制。innodb為...