? 在MySQL的引擎Innodb中,默認的transaction isolation即為REPEATABLE-READ。
下面,從非純技術角度,結合各種參考資料,分析一下REPEATABLE-READ的實現原理。
#1 知識準備。
##1.1? snapshot read
##2.2 current read
##3.3 MVVC(多版本并發控制)
##4.4 next-key。
#2?REPEATABLE-READ 實現效果(解決丟失更新,可重復讀)。
##2.1 略。(網絡中有詳細的效果截圖,自己也可以開多個seesion窗口實驗,不再贅述。)
(如果看到此處激動的同志,請看鏈接:https://tech.meituan.com/innodb-lock.html)
#3 基于上述文章的補充(翻譯:以上搬磚,以下.....額,只能說當時上學課堂流的口水,現在流的是眼淚,謹以此文,致歉我那上學時滔滔不絕的數據庫老教授)。
#3.1 關于snapshot read的補充。
? ?在上述文章中,提到讀加共享鎖,寫加排他鎖能夠避免不做事務的并發控制而出現的四種問題(參考:數據庫隔離級別),但是為了減少鎖的使用,提高讀的并發能力,基于MVCC的思想,設計出讀快照的方法。但是有些涉及到底層數據庫實現。
關鍵是解決:如何確定某行記錄對一個活躍的事務是否可見(是否能被當前事務select出來)。
在MySQL的每一行中,末尾存在三個隱藏的字段(到底是幾個,有說兩個的,這個說兩個的后來被人稱為是害人不淺,蒙蔽了真理。。。。網上也是眾說紛紜,稍有不慎就會迷失,但是基于那個兩個隱藏字段的理論確實不能解釋出現的現象,因此這個大牛說的是我本篇文章所認同的觀點:看這里,比我寫的好多了)。
在上述鏈接文章中,關于read veiw的解釋讓人茅塞頓開,一切現象得以解釋,因此可以基本認定是正確的。在此不再贅述。
#3.2 關于可重復讀的意外。
? ? ?在美團的那篇文章中,提到MySQL本身在REPEATABLE-READ級別就可以防止幻讀,我做了實驗,但是會出現意外,如以下截圖。
有人解釋說是因為update操作是實時讀,所以更新了select,但是這種解釋太粗了,我認為是更新了read view(未求證),因為MySQL的read commit的原理就是每次讀都更新read view。
#3.3 實踐指導思考。
###3.3.1 索引。
因為寫的時候會加排他鎖,所以,在寫的時候,能做到細粒度的鎖住最小的數據單元是很重要的,因此,添加合適并且適當的索引,避免間隙鎖,更要避免鎖表,是在設計數據庫和實際操作表中必須要考慮的。
###3.3.2 避免長時間事務所可重復讀帶來的數據不準確的問題。
未完待續......