mysql 並沒有幻讀 mysql幻讀

2021-10-13 12:05:05 字數 1840 閱讀 5438

幻讀(phantom read)

前提條件:innodb引擎,可重複讀隔離級別,使用當前讀時。

表現:乙個事務(同乙個read view)在前後兩次查詢同一範圍的時候,後一次查詢看到了前一次查詢沒有看到的行。兩點需要說明:

1、在可重複讀隔離級別下,普通查詢是快照讀,是不會看到別的事務插入的資料的,幻讀只在當前讀下才會出現。

2、幻讀專指新插入的行,讀到原本存在行的更新結果不算。因為當前讀的作用就是能讀到所有已經提交記錄的最新值。

幻讀的影響

會造成乙個事務中先產生的鎖,無法鎖住後加入的滿足條件的行。

產生資料一致性問題,在乙個事務中,先對符合條件的目標行做變更,而在事務提交前有新的符合目標條件的行加入。這樣通過binlog恢復的資料是會將所有符合條件的目標行都進行變更的。

幻讀產生的原因

行鎖只能鎖住行,即使把所有的行記錄都上鎖,也阻止不了新插入的記錄。

如何解決幻讀

將兩行記錄間的空隙加上鎖,阻止新記錄的插入;這個鎖稱為間隙鎖。

間隙鎖與間隙鎖之間沒有衝突關係。跟間隙鎖存在衝突關係的,是往這個間隙中插入乙個記錄這個操作。

快照讀:讀取的是記錄資料的可見版本(可能是過期的資料),不用加鎖。

當前讀:讀取的是記錄資料的最新版本,並且當前讀返回的記錄都會加上鎖,保證其他事務不會再併發的修改這條記錄

,舉個例子,假設你開啟了兩個事務,分別是a和b,這裡有張user表,裡面有四條資料

id     username     password         isadmin     name     type

1    vision        123456        1     趙    book

2    peter        123456        0    錢    test

3    bill        123456        0    孫    shop

4    tom        111111        0    李    shop

1、select快照讀(**)

當你執行select *之後,在a與b事務中都會返回4條一樣的資料,這是不用想的,當執行select的時候,innodb缺省會執行快照讀,相當於就是給你目前的狀態找了一張**,以後執行select 的時候就會返回當前**裡面的資料,當其他事務提交了也對你不造成影響,和你沒關係,這就實現了可重複讀了,那這個**是什麼時候生成的呢?不是開啟事務的時候,是當你第一次執行select的時候,也就是說,當a開啟了事務,然後沒有執行任何操作,這時候b insert了一條資料然後commit,這時候a執行 select,那麼返回的資料中就會有b新增的那條資料......之後無論再有其他事務commit都沒有關係,因為**已經生成了,而且不會再生成了,以後都會參考這張**。

2、update、insert、delete 當前讀

當你執行這幾個操作的時候缺省會執行當前讀,也就是會讀取最新的記錄,也就是別的事務提交的資料你也可以看到,這很好理解,假設你要update乙個記錄,另乙個事務已經delete這條資料並且commit了,這樣不是會產生衝突嗎,所以你update的時候肯定要知道最新的資訊啊。

我在這裡介紹一下update的過程吧,首先會執行當前讀,然後把返回的資料加鎖,之後執行update。加鎖是防止別的事務在這個時候對這條記錄做什麼,預設加的是排他鎖,也就是你讀都不可以,這樣就可以保證資料不會出錯了。但注意一點,就算你這裡加了寫鎖,別的事務也還是能訪問的,是不是很奇怪?資料庫採取了一致性非鎖定讀,別的事務會去讀取乙個快照資料。

innodb預設隔離級別是rr, 是通過mvvc來實現了,讀方式有兩種,執行select的時候是快照讀,其餘是當前讀,所以,mvvc不能根本上解決幻讀的情況。

標籤:事務,快照,記錄,幻讀,mysql,資料,select

React Native 並沒有死!

雖然廠商紛紛棄react native而去,但我相信facebook不會輕言放棄,廠商的離去反而會讓facebook更好的審視react native優缺點,在這次的大規模重構中,解決廠商提出的一些問題,並且會吸收flutter和vue.js的優點,從而使react native與原生架構結合得更好...

mysql幻讀 mysql 幻讀

幻讀 phantom read 是指當使用者讀取某一範圍的資料行時,b事務在該範圍內插入了新行,當使用者再讀取該範圍的資料行時,會發現有新的 幻影 行。innodb和falcon儲存引擎通 過多版本併發控制機制解決了幻讀問題。a事務讀取了b事務已經提交的新增資料,此時 a 還沒有提交,當前提交後,也...

AsyncTask的execute並沒有立即執行

原因不講了,也講不清楚,解決方案就是利用executeonexecutor設定自己的佇列,從而在舊頁面關閉前能及時清理當前頁面發出的資料請求 ps tasks為乙個arraylist,用來儲存當前介面所有產生的task,executeonexecutor能清除等待中的task們,cancle tru...