mysql可重複讀和幻讀例項

2021-07-31 08:59:42 字數 2101 閱讀 7327

mysql的預設事務級別是:可重複讀

其中可重複讀是通過mvcc來實現的又叫快照讀,在事務中的讀操作通過對當前的資料庫中記錄乙個版本,以後的讀操作只會讀取記錄的版本,因此相當於對資料庫的資料建立了乙個快照資料,因此叫做快照讀,其不用對資料庫中的資料進行加鎖又叫做樂觀鎖。

同時rr事務級別的mysql通當前讀和gap鎖來解決幻讀,其本質是通過對資料庫周邊記錄進行加悲觀鎖(讀鎖(共享鎖)和互斥鎖(寫鎖))【gap鎖】來解決幻讀。

rr事務隔離級別號稱可以解決幻讀的問題(通過當前讀加鎖來實現)

第一步建表並插入5條記錄:

接下來我們看下大部分mysql所說的幻讀現象:

事務1(開啟事務查詢發現沒有記錄6準備插入):

事務2(開啟事務,發現沒有記錄6插入,並提交事務):

事務1:查詢發現沒有記錄6,現在開始進行插入6:

沒有的記錄我要插入卻告訴已經存在,這就是通常說的幻讀。

mysql說對資料加鎖不管共享鎖還是互斥鎖就能解決幻讀的問題

開啟乙個事務1(加上共享鎖解決幻讀的情況):

開啟事務2(查詢發現沒有記錄8,準備插入)

可以發現事務2被阻塞,不准插入,除非事務1提交。因此在事務1中插入記錄8是能夠成功的。

事務1插入記錄8,最後可以查詢出自己插入的資料,但是更新一條不存在的資料是不會查詢出來的,最後提交事務:

事務2阻塞的操作會爆重複異常:

因此對乙個事務加上悲觀鎖(共享鎖或者互斥鎖)是能夠保證幻讀不會出現的,並且誰先加鎖,誰就能夠保證check and insert是成功的。如果你需要每個事務的check and insert都能成功,那麼你不要加共享鎖,直接加互斥鎖。那麼事務會直接阻塞在加鎖階段,就不會出現check and insert 失敗的情況。

事務1加上互斥鎖

事務2也想加互斥鎖,boom你只能失敗:

場景:我們知道grap鎖能夠將右邊的記錄進行加鎖,因此我要統計表記錄的數量,我只需要對最大記錄加鎖就行了

事務1:對最大記錄互斥加鎖,準備計算表中記錄數量。發現數量為8,並且不存在3和4的記錄。

事務2:插入缺失記錄3和4成功,但是插入id為100的記錄被鎖住,ok事務2可以提交了。

事務1:在事務1在事務2插入資料後進行查詢總量,發現數量還是6,ok很完美

事務1:接下來我發現事務1中沒有3和4這條記錄,我進行一次無用的更新會發生什麼?

ok,最終問題終於出現了,為什麼我更新兩條不存在的記錄,我能夠更新成功,並且我再次統計的時候,數量新增了兩條?並且我重新讀取,發現結果不一樣了,不是說可以重複讀嗎?加鎖可以解決幻讀嗎?

ps:如果乙個事務裡面插入或者刪除會改變記錄的資料,這個是合理的不是幻讀。更新應該只會修改資料記錄,這個也是合理,同樣不是幻讀,都是可重複讀的。但是更新出現新的記錄就是一種異常的情況。

髒讀 幻讀 不可重複讀和可重複讀

github 髒讀 幻讀 不可重複讀和可重複讀 即acid 隔離級別 髒讀 dirty read 不可重複讀 nonrepeatable read 幻讀 phantom read 未提交讀 read uncommitted 可能可能 可能已提交讀 read committed 不可能可能 可能可重複...

Mysql事務 髒讀,可重複讀,幻讀 測試

1 開啟mysql的命令列,將自動提交事務給關閉 檢視是否是自動提交 1表示開啟,0表示關閉 select autocommit 設定關閉 set autocommit 0 2 資料準備 建立資料庫 create database tran 切換資料庫 兩個視窗都執行 use tran 準備資料 c...

MySQL可重複讀級別會不會造成幻讀

在 高效能mysql 一書中,是這樣描述的 根據書上的描述,mysql的可重複讀隔離級別通過mvcc機制,解決了幻讀的問題,所以不會造成幻讀 本文預設你已經知道以下的命令 1.查詢當前會話隔離級別 select tx isolation 2.設定當前會話隔離級別 set session transa...