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+行鎖+間隙鎖

 

什么是間隙鎖?

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

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

舉個例子:

根據主鍵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?

多版本並發控制(Multi-Version Concurrency Control, MVCC)

僅在讀提交可重復讀兩種隔離級別下生效

每行記錄字段都保存有  一個最近變更事務Id  一個最新刪除的事務Id

事務讀數據的原則就是: 讀版本號小於等於當前版本的數據(意思就是讀不到在當前事務之后修改的數據 避免了不可重復讀)

            讀刪除事務版本號大於等於當前版本的數據(意思就是如果這條數據在之后的事務里刪了,當前事務也不能再讀了) 

InnoDB實現mvcc 是通過 readview+undolog 來實現

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM