檢索條件number=13,向左取得最靠近的值11作為左區(qū)間,向右由于沒有記錄因此取得無窮大作為右區(qū)間,因此,session 1的間隙鎖的范圍(11,無窮大),如下圖所示:此表中沒有number=13的記錄的,innodb依然會為該記錄左右兩側加間隙鎖,間隙鎖的范圍(11,無窮大)。有人會問,為啥update news set id=14 where number=11會阻塞,但是update news set id=11 where number=11卻執(zhí)行成功呢?間隙鎖采用在指定記錄的前面和后面以及中間的間隙上加間隙鎖的方式避免數(shù)據(jù)被插入,此圖間隙鎖鎖定的區(qū)域是(11,無窮大),也就是記錄(id=13,number=11)之后不能再插入記錄,update news set id=14 where number=11這條語句如果執(zhí)行的話,將會被插入到(id=13,number=11)的后面,也就是在區(qū)間(11,無窮大)之間,由于該區(qū)間被間隙鎖鎖定,所以只能阻塞等待,而update news set id=11 where number=11執(zhí)行后是會被插入到(id=13,number=11)的記錄前面,也就不在(11,無窮大)的范圍內,所以無需等待,執(zhí)行成功。案例三:
session 1: starttransaction ; select * from news wherenumber=5forupdate;
檢索條件number=5,向左取得最靠近的值4作為左區(qū)間,向右取得11為右區(qū)間,因此,session 1的間隙鎖的范圍(4,5),(5,11),如下圖所示:有人會問,為啥insert into news value(9,12)會執(zhí)行成功?間隙鎖采用在指定記錄的前面和后面以及中間的間隙上加間隙鎖的方式避免數(shù)據(jù)被插入,(id=9,number=12)很明顯在記錄(13,11)的后面,因此不再鎖定的間隙范圍內。為啥update news set number=5 where id=1會阻塞?number=5的記錄的前面,后面包括中間都被封鎖了,你這個update news set number=5 where id=1根本沒法執(zhí)行,因為innodb已經把你可以存放的位置都鎖定了,因為只能等待。同理,update news set id=11 where number=11由于記錄(id=10,number=5)與記錄(id=13,number=11)中間的間隙被封鎖了,你這句sql也沒法執(zhí)行,必須等待,因為存放的位置被封鎖了。案例四:
session 1: starttransaction; select * from news wherenumber>4forupdate;
檢索條件number>4,向左取得最靠近的值4作為左區(qū)間,向右取無窮大,因此,session 1的間隙鎖的范圍(4,無窮大),如下圖所示:session2中之所以有些阻塞,有些執(zhí)行成功,其實就是因為插入的區(qū)域被鎖定,從而阻塞。next-key鎖next-key鎖其實包含了記錄鎖和間隙鎖,即鎖定一個范圍,并且鎖定記錄本身,InnoDB默認加鎖方式是next-key 鎖。上面的案例一session 1中的sql是:select * from news where number=4 for update ;next-key鎖鎖定的范圍為間隙鎖+記錄鎖,即區(qū)間(2,4),(4,5)加間隙鎖,同時number=4的記錄加記錄鎖。