MySQL可重復(fù)讀防止幻讀

接上篇事務(wù)隔離級(jí)別和幻讀,留了個(gè)坑,沒想到竟然過了10天,時(shí)間不注意真的過的好快。順便提下,簡(jiǎn)書圖片鏈接是屬于網(wǎng)站的,開發(fā)自己的圖床迫在眉睫,萬一哪天遷移就要做很多額外工作,一些概念或者思路用圖片表達(dá)更直觀清楚。
回到正題,之前提到一般情況下MySQL的InnoDB引擎在可重復(fù)讀的情況下是沒法保證不出現(xiàn)幻讀的,但實(shí)際情況是MySQL可以通過加鎖來防止幻讀的出現(xiàn),這種鎖定通過Next-key機(jī)制來實(shí)現(xiàn),是屬于記錄鎖和間隙鎖(Gap鎖)的結(jié)合。
引申,行級(jí)別鎖的三種算法:

  • Record lock
  • Gap lock
  • Next-Key lock
    record lock 按照索引記錄加鎖,如果沒有則采用隱式的主鍵來鎖定。
    next-key 結(jié)合了Gap lock 和 record lock ,例如索引值:10,11,13,20。則按next-key 鎖定的區(qū)間為(-∞,10],(10,11]
    ,(11,13],(13,20],(20,+∞)

注意此處指非唯一索引,如果是唯一索引,會(huì)降級(jí)為Record lock ,僅僅鎖住索引本身,而非范圍。同時(shí)這種降級(jí)只發(fā)生在查詢所有索引列的情況下,如果存在聯(lián)合索引且只是查詢聯(lián)合索引的某一列,即屬于range類型查詢,仍是采用Next-key鎖定,不會(huì)降級(jí)。

舉個(gè)存在唯一索引和輔助索引的例子做說明:

create table test ( a int , b int , primary key (a), key(b));
insert into test select 1, 1;
insert into test select 3, 1;
insert into test select 5, 3;
insert into test select 7, 6;
insert into test select 10,8;

執(zhí)行 select * from test where b = 3 for update
存在兩個(gè)索引,分別加鎖,唯一主鍵列a加record lock , 輔助索引列b加next-key lock (1,3) 以及給下一個(gè)值的區(qū)間(3,6)加gap鎖;
因此在另一個(gè)事務(wù)里執(zhí)行以下語(yǔ)句都會(huì)阻塞,具體分析:

select * from test where a = 5 lock in share mode;
insert into test select 4,2;
insert into test select 6,5;

第一個(gè)阻塞因?yàn)榧恿宋ㄒ凰饕膔ecord lock a = 5;
第二個(gè)主鍵插入4,符合條件,但是根據(jù)輔助索引b 的范圍, b = 2 在(1,3)中,同樣阻塞;
第三個(gè)a =6 不在主鍵a鎖定范圍,b = 5 也不在輔助索引b 的范圍(1,3)中,但在另一個(gè)gap鎖范圍(3,6)中,因此也阻塞;
這種鎖定情形下,可以執(zhí)行的包括類似語(yǔ)句:

insert into test select 8,6; 
insert into test select 2,0;

gap lock 可以通過設(shè)置隔離級(jí)別為讀已提交或者將innodb_locks_unsafe_for_binlog = 1取消,但是從隔離性,性能,以及主從數(shù)據(jù)一致等方面都不建議這樣做。

insert的特殊情況
對(duì)于insert 會(huì)檢查下一條記錄是否被鎖定,如上述例子有select * from test where b = 3 for update插入insert into test select 2,2會(huì)檢測(cè)到b = 3 已經(jīng)被鎖定,而insert into test select 2,0可以執(zhí)行;

[1]:《MySQL技術(shù)內(nèi)幕:InnoDB存儲(chǔ)引擎》-第六章:鎖

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容