天天看點

mysql MVCC+間隙鎖解決幻讀了解

mysql的隔離級别?

讀未送出 -》 讀送出 -》 可重複讀 -》 串行化

InnoDB預設級别為可重複讀,可重複讀會産生問題 就是幻讀。

什麼是幻讀?

不可重複讀側重于update這種操作,同一條資料前後讀起來不一樣的情況,

幻讀側重于insert delete這種操作,前後兩次select 資料的數量會發生變化

舉個例子:

事務A 第一步 select * 第二步 update 所有字段 第三步 再次select *

事務B 執行了insert 一條語句

幻讀第一種情況: 當事務A 剛執行完第一步,事務B insert一條,導緻事務A update執行完,再次select發現多了一條資料

幻讀第二種情況: 當事務A 剛執行完第二步,事務B insert一條,導緻事務A 再次select 發現有一條資料沒有update字段

InnoDB如何解決幻讀的?

Mvcc+行鎖+間隙鎖

什麼是間隙鎖?

正常等值條件 并且值存在的情況下加的是行鎖

如果等值條件 值不存在的情況下加的是間隙鎖,或者範圍查詢,加的也是間隙鎖

舉個例子:

mysql MVCC+間隙鎖解決幻讀了解

根據主鍵id,不隻是有五個行鎖,還會有六個間隙鎖,左開右閉原則,(-∞,5](5,10](10,15](15,20](20,25](25,+supernum]

例如 select * from table where id = 10 for update; 等值條件,id是存在的,加行鎖就可以了

select * from table where id = 7 for update; 等值條件,id不存在,加(5,10] 間隙鎖,這範圍間不允許插入資料,直到這個事務送出完成釋放鎖

select * from table where id > 24; 範圍條件,加間隙鎖

通過行鎖+間隙鎖的機制保證了事務A select之後,其他事務相應的insert操作會阻塞

什麼是undolog?

undolog存放不同僚務版本下的不同資料,

用于 1.曆史恢複 通過undolog恢複之前版本的資料 2. 讀老版本 根據條件讀舊版本的資料

每次資料變更都會産生undolog記錄,undolog記錄分為 insert undo_log 和 update undo_log

insert操作屬于insert undo_log,隻針對目前事務,在insert操作後産生undo_log記錄,在事務送出後删除undo_log記錄,說白了就是給目前事務自己看的.

update 和 delete操作屬于update undo_log,會根據隔離級别不同僚務版本的資料可見性不同

什麼是readView?

快照 存放了目前活躍的一些事務版本号,以及上一個版本的位址. 用來做可見性判斷

readview根據生成時間不同,産生了RC,RR兩種可見性

RC:每條select建立一個新的readview ,是以導緻讀送出 讀到的都是最新送出的!

RR:事務開始的時候建立一個readview, 一直到事務結束都用的這個readview,也就避免了不可重複讀

目前讀與快照讀

單條普通的select語句屬于快照讀

select for update , insert, update, delete 屬于目前讀

快照讀由mvcc+undolog實作

目前讀由行鎖+間隙鎖實作

什麼是MVCC?

繼續閱讀