日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

实现mvcc_MySQL 的多版本并发控制(MVCC) 是干啥的?

發布時間:2024/9/27 数据库 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 实现mvcc_MySQL 的多版本并发控制(MVCC) 是干啥的? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

點擊藍色“架構文摘”關注我喲

加個“星標”,每天上午 09:25,干貨推送!

來源:https://segmentfault.com/a/1190000037557620
作者:白菜1031

一、什么是多版本并發控制

多版本并發控制 技術的英文全稱是 Multiversion Concurrency Control ,簡稱 MVCC

多版本并發控制(MVCC)
是通過保存數據在某個時間點的快照來實現并發控制的。也就是說,不管事務執行多長時間,事務內部看到的數據是不受其它事務影響的,根據事務開始的時間不同,每個事務對同一張表,同一時刻看到的數據可能是不一樣的。

簡單來說, 多版本并發控制
的思想就是保存數據的歷史版本,通過對數據行的多個版本管理來實現數據庫的并發控制。這樣我們就可以通過比較版本號決定數據是否顯示出來,讀取數據的時候不需要加鎖也可以保證事務的隔離效果。

可以認為 多版本并發控制(MVCC)
是行級鎖的一個變種,但是它在很多情況下避免了加鎖操作,因此開銷更低。雖然實現機制有所不同,但大都實現了非阻塞的讀操作,寫操作也只鎖定必要的行。

MySQL的大多數事務型存儲引擎實現的都不是簡單的行級鎖?;谔嵘l性能的考慮,它們一般都同時實現了多版本并發控制(MVCC)。不僅是MySQL,包括Oracle、PostgreSQL等其他數據庫系統也都實現了MVCC,但各自的實現機制不盡相同,因為MVCC沒有一個統一的實現標準,典型的有樂觀(optimistic)并發控制悲觀(pessimistic)并發控制 。

二、多版本并發控制解決了哪些問題

1. 讀寫之間阻塞的問題

通過 MVCC 可以讓讀寫互相不阻塞,即讀不阻塞寫,寫不阻塞讀,這樣就可以提升事務并發處理能力。

提高并發的演進思路:

  • 普通鎖,只能串行執行;

  • 讀寫鎖,可以實現讀讀并發;

  • 數據多版本并發控制,可以實現讀寫并發。

2. 降低了死鎖的概率

因為 InnoDB 的 MVCC 采用了樂觀鎖的方式,讀取數據時并不需要加鎖,對于寫操作,也只鎖定必要的行。

3. 解決一致性讀的問題

一致性讀也被稱為 快照讀
,當我們查詢數據庫在某個時間點的快照時,只能看到這個時間點之前事務提交更新的結果,而不能看到這個時間點之后事務提交的更新結果。

三、快照讀與當前讀

快照讀(SnapShot Read) 是一種 一致性不加鎖的讀 ,是 InnoDB并發如此之高的核心原因之一

這里的 一致性 是指,事務讀取到的數據,要么是 事務開始前就已經存在的數據 ,要么是 事務自身插入或者修改過的數據 。

不加鎖的簡單的 SELECT 都屬于 快照讀 ,例如:

????`SELECT?*?FROM?t?WHERE?id=1`

快照讀 相對應的則是 當前讀當前讀 就是讀取最新數據,而不是歷史版本的數據。加鎖的 SELECT 就屬于當前讀,例如:

????SELECT?*?FROM?t?WHERE?id=1?LOCK?IN?SHARE?MODE;

????SELECT?*?FROM?t?WHERE?id=1?FOR?UPDATE;

四、InnoDB 的 MVCC 是如何工作的

1. InnoDB 是如何存儲記錄的多個版本的

事務版本號

每開啟一個事務,我們都會從數據庫中獲得一個事務 ID(也就是事務版本號),這個事務 ID 是自增長的,通過 ID 大小,我們就可以判斷事務的時間順序。

行記錄的隱藏列

InnoDB 的葉子段存儲了數據頁,數據頁中保存了行記錄,而在行記錄中有一些重要的隱藏字段:

  • DB_ROW_ID :6-byte,隱藏的行 ID,用來生成默認聚簇索引。如果我們創建數據表的時候沒有指定聚簇索引,這時 InnoDB 就會用這個隱藏 ID 來創建聚集索引。采用聚簇索引的方式可以提升數據的查找效率。

  • DB_TRX_ID :6-byte,操作這個數據的事務 ID,也就是最后一個對該數據進行插入或更新的事務 ID。

  • DB_ROLL_PTR :7-byte,回滾指針,也就是指向這個記錄的 Undo Log 信息。

InnoDB數據記錄隱藏列
Undo Log

InnoDB 將行記錄快照保存在了 Undo Log 里,我們可以在回滾段中找到它們,如下圖所示:

Undo Log回滾歷史記錄

從圖中能看到回滾指針將數據行的所有快照記錄都通過鏈表的結構串聯了起來,每個快照的記錄都保存了當時的 db_trx_id,也是那個時間點操作這個數據的事務
ID。這樣如果我們想要找歷史快照,就可以通過遍歷回滾指針的方式進行查找。

2. 在 可重復讀(REPEATABLE READ) 隔離級別下, InnoDB 的 MVCC 是如何工作的

查詢(SELECT)

InnoDB 會根據以下兩個條件檢查每行記錄:

  • InnoDB只查找版本早于當前事務版本的數據行(也就是,行的系統版本號小于或等于事務的系統版本號),這樣可以 確保事務讀取的行,要么是在事務開始前已經存在的,要么是事務自身插入或者修改過的 。

  • 行的刪除版本要么未定義,要么大于當前事務版本號。這可以確保 事務讀取到的行,在事務開始之前未被刪除 。

  • 只有符合上述兩個條件的記錄,才能返回作為查詢結果。

    插入(INSERT)

    InnoDB為新插入的每一行保存當前系統版本號作為行版本號。

    刪除(DELETE)

    InnoDB為刪除的每一行保存當前系統版本號作為行刪除標識。?
    刪除在內部被視為更新,行中的一個特殊位會被設置為已刪除。

    更新(UPDATE)

    InnoDB為插入一行新記錄,保存當前系統版本號作為行版本號,同時保存當前系統版本號到原來的行作為行刪除標識。

    五、總結

    多版本并發控制(MVCC) 在一定程度上實現了 讀寫并發 ,它只在 可重復讀(REPEATABLE READ)提交讀(READ COMMITTED) 兩個隔離級別下工作。其他兩個隔離級別都和 MVCC 不兼容,因為 未提交讀(READ UNCOMMITTED) ,總是讀取最新的數據行,而不是符合當前事務版本的數據行。而 可串行化(SERIALIZABLE)
    則會對所有讀取的行都加鎖。

    行鎖,并發,事務回滾 等多種特性都和MVCC相關。

    參考

    MySQL5.7文檔:innodb-multi-versioning ?
    《高性能MySQL》

    end

    推薦閱讀:

    • TCP 三次握手、四手揮手,這樣說你能明白吧!

    • 拜托,不要再問我線程池啦!

    • 為什么 Redis 單線程還這么快?

    • Spring Cloud架構的各個組件的原理分析

    • 一口氣說出 5 種 IO 模型,蒙圈了!

    如有收獲,點個在看,誠摯感謝

    總結

    以上是生活随笔為你收集整理的实现mvcc_MySQL 的多版本并发控制(MVCC) 是干啥的?的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。