InnoDB在MySQL預設隔離級別下解決幻讀

2022-05-17 01:39:12 字數 2330 閱讀 9568

在rr的隔離級別下,innodb使用mvvc和next-key locks解決幻讀,mvvc解決的是普通讀(快照讀)的幻讀,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產生的影響,這個影響叫做「幻讀」。

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

3.1. 當前讀

所謂當前讀,指的是加鎖的select(s或者x), update, delete等語句。在rr的事務隔離級別下,資料庫會使用next-key locks來鎖住本條記錄以及索引區間。

拿上面那個例子來說,在rr的情況下,假設使用的是當前讀,加鎖了的讀

select * from table where id>3 鎖住的就是id=3這條記錄以及id>3這個區間範圍,鎖住索引記錄之間的範圍,避免範圍間插入記錄,以避免產生幻影行記錄。

因為普通讀是不會加鎖的讀,故不會有next-key locks的使用,解決幻讀的手段是mvvc

mvvc會給每行元組加一些輔助字段,記錄建立版本號和刪除版本號。

而每乙個事務在啟動的時候,都有乙個唯一的遞增的版本號。每開啟乙個新事務,事務的版本號就會遞增。

預設的隔離級別(repeatable read)下,增刪查改變成了這樣:

select

讀取建立版本小於或等於當前事務版本號,並且刪除版本為空或大於當前事務版本號的記錄。這樣可以保證在讀取之前記錄是存在的

insert

將當前事務的版本號儲存至行的建立版本號

update

新插入一行,並以當前事務的版本號作為新行的建立版本號,同時將原記錄行的刪除版本號設定為當前事務版本號

delete

將當前事務的版本號儲存至行的刪除版本號

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

idname

createversion

deleteversion

1wxt

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

idname

createverison

deleteversion

1wxt12

1taotao

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

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

idname

createverison

deleteversion

1taotao23

重點來了

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

讀取建立版本小於或等於當前事務版本號   這意味著資料在這個事務之前被建立

刪除版本為空或大於當前事務版本號的記錄。  這意味著刪除操作在這個事務之後發生

假設事務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)

Mysql 事務隔離級別 InnoDB實現隔離機制

在read uncommitted級別中,事務所做的寫操作,即使沒有提交,對其他事務也是可見的,a事務可以讀取b事務未提交的資料,這就叫做未提交讀 髒讀。這個級別會導致很多問題,但從效能上來說,並不比其他級別好太多。大部分資料庫系統的預設隔離級別就是 read committed,它解決了髒讀的問題...

MySQL預設引擎InnoDB自動提交事務設定

1.檢視當前自動提交事務屬性狀態,show variables like autocommit 工具裡用一樣的語句,命令列好截圖 當前狀態為 on 自動提交事務 2.關閉自動提交事務,改為手動,set autocommit 0 0 關閉,1 開啟 通過這兩步就已經設定好了mysql事務手動commi...

更改mysql預設引擎為Innodb 單個多個

mysql預設是關閉innodb儲存引擎的使用的,將innodb設定為預設的引擎如下。1.檢視mysql儲存引擎情況 mysql show engines。innodb yes,說明此mysql資料庫伺服器支援innodb引擎。2.設定innodb為預設引擎 在配置檔案my.ini中的 mysqld...