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

2021-10-11 21:30:13 字數 2503 閱讀 3073

在《高效能mysql》一書中,是這樣描述的

根據書上的描述,mysql的可重複讀隔離級別通過mvcc機制,解決了幻讀的問題,所以不會造成幻讀

本文預設你已經知道以下的命令

1. 查詢當前會話隔離級別

select @@tx_isolation

;

2. 設定當前會話隔離級別

set

session

transaction

isolation

level

repeatable

read

;

3. 查詢正在進行中的事務

select

*from information_schema.innodb_trx

準備實驗的表和資料

create

table

`user`(

`id`

int(11)

notnull

auto_increment

,`name`

varchar(30

)default

null

,`age`

tinyint(4

)default

null

,primary

key(

`id`))

;insert

into

user

values(1

,'張三',1

);

測試表資料如下:

開啟兩個會話視窗,分別都設定隔離級別為rr

按照順序執行以下操作

事務a事務b

start transaction

select * from user

—③start transaction

—④insert into user values(2,'李四',1)

—⑤commit

select * from user

update user set age = 2

select * from user

按照上圖序號標註的順序,從①到⑥,在⑥查詢的時候,發現確實是沒有查到b事務新增的資料的,所以確實沒有幻讀。但是再執行⑦、⑧,會發現在⑧的時候,出現了幻讀

這裡預設你已經知道了mvcc的原理,可以參考這篇文章mysql mvcc實現原理

簡單來說,就是mysql會預設給表增加兩個字段,乙個是標記建立時間,乙個標記過期時間(也是刪除時間),這裡的時間指的是當前事務的id

select

innodb會根據以下兩個條件檢查每行記錄:

只有符合上述兩個條件的記錄,才能返回作為查詢結果

insert

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

delete

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

update

innodb為插入一行新記錄,儲存當前系統版本號作為行版本號,同時儲存當前系統版本號到原來的行作為行刪除標識。

帶上這兩個字段,分析下測試資料

執行完②

idname

age建立時間

刪除時間1張三

11執行完⑤

idname

age建立時間

刪除時間1張三

112李四

12執行⑥的時候,根據select的時候版本號規則,查詢小於等於當前版本號,所以只能查出id = 1的資料,沒有幻讀

執行完⑦

idname

age建立時間

刪除時間1張三

112李四

1212

李四11根據update的版本號規則,現在資料庫應該有三條資料

所以再執行⑧的查詢,根據select的查詢規則,應該是能看到新增的資料,產生了幻讀

所以我認為mysql的mvcc機制並沒有完全解決幻讀問題。

這是我自己的理解,如果有誤還請指出

mysql 可重複讀。

一 可重複讀 我們先看看現象,再分析原理。我的mysql版本是5.5。下面是一張表,只有一條資料,並且我開啟了事物 此時,另乙個事物將record加1,因此我在開啟乙個命令列客戶端,執行下面的命令 成功加1之後,實際上,資料庫中record肯定是2。然後回到之前的客戶端,再查一次 沒毛病,recor...

mysql可重複讀

mysql innodb的預設隔離級別是可重複讀,之前理解有些偏差,查閱一些資料後總結出幾點 首先有兩個概念 一致性檢視 當乙個事務開啟時,innodb會生成乙個檢視,這個檢視是邏輯檢視,通過undo log和row tranzaction id控制實現。在該事務的任何時間點,一致性檢視中的資料都是...

MySQL事務隔離級別可重複讀測試

開啟rds,查詢當前的事務隔離級別select tx isolation查詢得到時候可重複讀,於是做了如下測試。可重複隔離級別的特點是,每個事務可以在乙個事務中可以反覆讀取資料,每次讀取到的資料都是相同的。在 高效能mysql 一書中,講到這種隔離級別很好的解決了髒讀問題,也就是讀取的資料都是事務開...