mvcc詳解

1 為什么需要MVCC

  • 用來進行事務回滾操作;

  • 有事務存在讀寫沖突時,也能做到不加鎖,非阻塞并發讀

2 undolog

2.1 undolog定義

在InnoDB中的每一條記錄實際都會存在三個隱藏列:

  • DB_TRX_ID:事務 ID,是根據事務產生時間順序自動遞增的,是獨一無二的。如果某個事務執行過程中對該記錄執行了增、刪、改操作,那么InnoDB存儲引擎就會記錄下該條事務的 id。

  • DB_ROLL_PTR:回滾指針,本質上就是一個指向記錄對應的undo log的一個指針,InnoDB 通過這個指針找到之前版本的數據

  • DB_ROW_ID:主鍵,如果有自定義主鍵,那么該值就是主鍵;如果沒有主鍵,那么就會使用定義的第一個唯一索引;如果沒有唯一索引,那么就會默認生成一個隱藏列作為主鍵。

image.png

版本V1、V2并不是物理上真實存在的,而是每次需要的時候根據當前版本和undo log計算出來的。比如,需要V1的時候,就是通過V3依次執行U2、U1算出來。

可以將這些 undo 日志都連起來,串成一個鏈表,形成版本鏈。版本鏈的頭節點就是當前記錄最新的值。

2.2 undo log分類

  • Insert undo log :insert生成的日志,僅在事務回滾中需要,并且可以在事務提交后立即丟棄。

  • Update undo log:update/delete生成的日志,除了用于事務回滾,還用于一致性讀取,只有不存在innodb為其分配快照的事務之后才能丟棄它們,在一致讀取中可能需要update undo log中的信息來構建數據庫行的早期版本。

2.3 數據刪除

刪除操作實際上不會直接刪除,而只是標記為刪除,最終的刪除操作是purge線程完成的

purge線程作用

1、清理undo log

2、清除page里面帶有Delete_Bit標識的數據行。在InnoDB中,事務中的Delete操作實際上并不是真正的刪除掉數據行,而是一種Delete Mark操作,在記錄上標識刪除,真正的刪除工作需要后臺purge線程去完成。

2.4 更新主鍵

聚簇索引和二級索引都無法進行in place update,都會產生兩個版本

update分兩步執行,先刪除該行,再插入一行目標行

image.png

2.5 更新非主鍵

聚簇索引可以in place update,二級索引產生兩個版本

聚簇索引記錄undo log,二級索引不記錄undo log

更新二級索引,同時需要判斷是否修改索引頁面的MAX_TRX_ID


image.png

2.6 刪除操作

刪除操作實際上不會直接刪除,而只是標記為刪除,最終的刪除操作是purge線程完成的

image.png

3 Read View

Read View是InnoDB在實現MVCC時用到的一致性讀視圖,用于支持讀提交和可重復讀隔離級別的實現,作用是執行期間判斷版本鏈中的哪個版本是當前事務可見的。

本質上是InnoDB為每個事務構造了一個數組,用來保存當前正在活躍(啟動了但還沒提交)的所有事務ID。

數組里面事務ID的最小值記為低水位,當前系統里面已經創建過的事務ID的最大值加1記為高水位;這個視圖數組和高水位,就組成了當前事務的一致性視圖(read-view)。

對于以上事務:

  1. 如果在「已提交事務」部分,表示這個版本是已提交的事務或者是當前事務自己生成的,這個數據對當前事務是可見的;

  2. 如果落在「未開啟事務」部分,表示這個版本是由將來啟動的事務生成的,是肯定不可見的;

  3. 如果落在「未提交」部分,那就包括兩種情況
    a. 若當前版本的trx_id在一致性試圖中,表示這個版本是由還沒提交的事務生成的,不可見;
    b. 若當前版本的trx_id不在一致性試圖中,表示這個版本是已經提交了的事務生成的,可見。

3 MVCC的工作原理

3.1 MVCC查詢的工作流程

3.1.1 查詢主鍵索引

生成Read View讀視圖

通過主鍵查找記錄,根據記錄里的DB_TRX_ID與Read View讀視圖進行可見性判斷

配合DB_ROLL_PTR回滾指針和undo log來找到當前事務可見的數據記錄

3.1.2 查詢二級索引

由于二級索引由于沒有三個隱藏列(DB_TRX_ID,DB_ROLL_PTR,DB_ROW_ID)如何實現一致讀,可重復讀?

更新二級索引列時,舊的二級索引記錄將被刪除標記(并非真正的刪除),新記錄將被插入;

如果二級索引記錄被標記為刪除,或者二級索引頁被更新的事務更新,則不使用覆蓋索引技術(要通過聚族索引查找正確版本)。

如果啟用了索引條件下推(ICP)優化,首先會通過索引下推過濾掉不符合要求的行,來避免使用聚集索引查找。如果找到匹配的記錄,即使在刪除標記的記錄中,InnoDB也會在聚集索引中查找該記錄。

具體查詢步驟:

  • 生成Read View讀視圖

  • 比較讀視圖的up_limit_id與MAX_TRX_ID大小

    • 如果MAX_TRX_ID **小于 **本次Read View的up_limit_id,則全部可見,過濾記錄中的有效記錄

    • 否則,無法通過二級索引判斷可見性,需要一次遍歷每條記錄,反查到聚簇索引記錄,通過聚簇索引記錄來判斷可見性

3.2 MVCC與隔離級別

MVCC 只在 **Read Commited(讀已提交) 和 Repeatable Read(可重讀讀) **兩種隔離級別下工作。

  • 在RC隔離級別下,是每個快照讀都會生成并獲取最新的Read View,這就是我們在RC級別下的事務中可以看到別的事務提交的更新的原因

  • 在RR隔離級別下,則是同一個事務中的第一個快照讀才會創建Read View, 之后的快照讀獲取的都是同一個Read View,從而做到可重復讀

3.3 mvcc能否解決幻讀

幻讀:在一次事務里面,多次查詢之后,結果集的個數不一致的情況叫做幻讀。而多出來或者少的哪一行被叫做幻行。

  • 在快照讀讀情況下,mysql通過mvcc來避免幻讀。

  • 在當前讀讀情況下,mysql通過next-key來避免幻讀。

  • 不能把快照讀和當前讀得到的結果不一樣這種情況認為是幻讀,這是兩種不同的使用。所以mysql的rr級別是解決了幻讀的。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內容

  • Innodb-MVCC詳解 借用高性能 MySQL 的幾句話 MySQL 的大多數事務型存儲引擎都不是簡單的行級鎖...
    mago_dg閱讀 1,258評論 0 1
  • 1 mvcc是什么? 阿里數據庫內核2017/12月報多版本控制: 指的是一種提高并發的技術。最早的數據庫系統,只...
    Aaron_Swartz閱讀 15,320評論 0 7
  • 1. MVCC的基本概念 1.1 三種數據庫并發場景 讀-讀:不存在任何問題,也不需要并發控制 讀-寫:有線程安全...
    小青菜的技術博客閱讀 4,715評論 1 41
  • 最近要在公司內做一次技術分享,思來想去不知道該分享些什么,最后在朋友的提示下,準備分享一下MySQL的InnoDB...
    阿Q說代碼閱讀 594評論 0 3
  • 深入了解MVCC數據庫并發控制 問題: 我們知道這個是因為數據庫的隔離級別,那到底是怎么實現的呢?思考這個問題的同...
    e0e180156aa8閱讀 2,545評論 0 8