MySQL談談InnoDB怎麼解決幻讀的

2021-10-09 15:03:57 字數 2321 閱讀 9338

首先說結論,在rr的隔離級別下,innodb使用mvcc和next-key locks解決幻讀,mvcc解決的是普通讀(快照讀)的幻讀,next-key locks解決的是當前讀情況下的幻讀。

事務a,先執行:

update table set name=「hh」 where id>3;
結果為:

ok row xx 表名成功影響多少行資料

事務b,後執行,並且提交:

insert into table values(11, uu);

commit;

事務a,然後再select一下:

select * from table where id>3
結果集為:

… 11,uu …

事務a懵了,我特麼不是id>3全部更新了嗎

這次是已提交事務b對事務a產生的影響,這個影響叫做「幻讀」。

幻讀和不可重複讀的區別是,前者是乙個範圍,後者是本身

所謂當前讀,指的是加鎖的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)下,增刪查改變成了這樣:

select

insert

update

delete

比如我插入一條記錄, 事務id 假設是1 ,那麼記錄如下:也就是說,建立版本號就是事務版本號。

如果我更新的話,事務id假設是2

這裡是把name更新為taotao,原來的元組deleteversion版本號為這個事務的id,並且新增一條

如果我刪除的話,假設事務是id=3        

就變成現在這個樣子

關鍵點來了

現在我讀取的話,必須同時滿足兩個條件的

就拿上面那個例子說明

當前資料庫的狀態

假設事務a的id=10

現在update table set name=「hh」 where id>3;執行這條語句

事務b的id=11

最後事務a(id=10)在此讀取

select * from table where id>3
根據上述的規則,讀取建立版本好小於等於當前事務的→那麼(4,a)(5,b)(4,hh)(5,hh)

上面規則的輸出作為下面規則的輸入的話,刪除版本為空或大於當前事務版本號的記錄→(4,hh)(5,hh)

如此讀取就沒有讀取到事務b新插入的那行,解決幻讀

如果事務b是更新id=4 的元組name=cc呢

同理,根據update的規則

然後根據select的規則去讀取的話,得到的還是(4,hh)(5,hh)

在rc的模式下,mvcc解決不了幻讀和不可重複讀,因為每次讀都會讀它自己重新整理的快照版本,簡單來說就是另乙個事務提交,他就重新整理一次,去讀最新的

InnoDB怎麼解決幻讀的?

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

InnoDB 怎麼做表空間遷移

在工作中經常會碰到單獨遷移 複製或者備份某一張表的需求,一般可以通過邏輯 物理備份來實現。但是在 5.6.6 的版本中我們還可以用到一種基於表空間遷移的快速方法,本節內容就來聊聊這一操作。2實戰 實驗環境 兩個 mysql 5.7.22 版本資料庫例項。測試步驟如下 2.1在源庫建立一張測試表 my...

mysql日誌 InnoDB 監控

參考官方文件 innodb監視器提供有關innodb內部狀態的資訊。此資訊對效能調整很有用。14.17.1 innodb 監控型別 innodb監視器有兩種型別 innodb鎖定監視器列印額外的鎖定資訊作為標準innodb監視器輸出的一部分。14.17.2 啟用 innodb 監控 當innodb監...