此次的內容是學習極客時間的MySQL實戰45講課程中的實驗和總結,具體課程是第21篇文章。sql
首先是課程中的總結的加鎖規則,兩個「原則」、兩個「優化」和一個「bug」(可重複讀的事務隔離級別下)。學習
原則 1:加鎖的基本單位是 next-key lock。但願你還記得,next-key lock 是前開後閉區間。 原則 2:查找過程當中訪問到的對象纔會加鎖。 優化 1:索引上的等值查詢,給惟一索引加鎖的時候,next-key lock 退化爲行鎖。 優化 2:索引上的等值查詢,向右遍歷時且最後一個值不知足等值條件的時候,next-key lock 退化爲間隙鎖。 一個 bug:惟一索引上的範圍查詢會訪問到不知足條件的第一個值爲止。
而後是此次用到的表和數據優化
CREATE TABLE `t` ( `id` int(11) NOT NULL, `c` int(11) DEFAULT NULL, `d` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `c` (`c`) ) ENGINE=InnoDB; insert into t values(0,0,0),(5,5,5), (10,10,10),(15,15,15),(20,20,20),(25,25,25);
再而後就是實際例子了3d
根據原則1加的next-key lock鎖是id(5,10],由於id等於7的數據並不存在,因此不知足優化1,根據優化2將會退化爲間隙鎖id(5,10),從上面的實際例子中也能看出來,只有插入id=6的數據在等待鎖,id=四、十一、十、5的數據在插入和更新的時候都正常。對象
這個和上一個例子相似區別是知足優化1因此就從next-key lock鎖id(5,10],退化爲id=5的行鎖,因此id=6,4的數據能夠插入進去,只有id=5的數據在更新的時候等待鎖。blog
這種狀況就是索引
因此id=四、11的數據能夠插入,而id=六、10的數據的更新和插入的時候須要等待鎖事務
分析:it
可是實際狀況上id=11的數據插入也須要等待鎖,這就是上面規則說的bug惟一索引上的範圍查詢會訪問到不知足條件的第一個值爲止,這裏的id<=10,會一直掃描到id=15,因此會加上(10,15]的next-key lock鎖class
這實際上是兩個例子,由於只有一個區別就放一塊兒了,先按照規則來分析
這兩個加鎖的區別就是對於id=5的鎖的問題,lock in share mode沒有對id=5加鎖,因此能夠獲得的信息是,lock in share mode只鎖覆蓋索引,可是若是是 for update 就不同了。 執行 for update 時,系統會認爲你接下來要更新數據,所以會順便給主鍵索引上知足條件的行加上行鎖。
這個和3例子相似,區別是這裏不是主鍵,也就是說不是惟一索引,因此這裏的分析過程就是
這個例子和第5個例子相似,區別就是limit的問題,由於規則中總結的bug能夠解釋,limit 1只須要掃描一行,因此c(5,10)的間隙鎖就沒加上,而limit 2就再次證實了,若是須要返回兩條數據須要再掃描就加上了c(5,10)的間隙鎖
沒有order by的狀況先來分析:
而後是有order by desc的狀況:
這上面總結的規則,其實沒啥道理可言,MySQL代碼就是這樣寫的,加鎖的意義是實際上爲了保持數據的一致性和語義的正確,從例子4咱們就能看到明明咱們想鎖的是5-10,可是由於bug(10,15]也加上了鎖。因此考慮MySQL的這個加鎖問題的時候,最好仍是根據掃描的狀況來考慮
而後是一些細節的記錄: