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 來實現
