日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

你是否對MySQL數據庫中的事務已經有所了解?看下面這張圖,按照1~6的順序依次執行,在RR隔離級別下,事務A和事務B各自輸出的num值是多少嗎?

日常學習MySQL底層之MVCC、回滾段、一致性讀、鎖定讀

 

我們預先創建好這樣一張表并初始化一條數據:

CREATE TABLE `test1`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵Id',
  `num` int(11) NULL COMMENT '數量',
  PRIMARY KEY (`id`)
) ENGINE = InnoDB;
insert into test1(id, num) values (1, 1);

然后開始按上圖的順序執行各個事務,這需要我們打開3個操作窗口來分別執行A、B、C三個事務:

事務A:

日常學習MySQL底層之MVCC、回滾段、一致性讀、鎖定讀

事務A

事務B:

日常學習MySQL底層之MVCC、回滾段、一致性讀、鎖定讀

事務B

事務C:

日常學習MySQL底層之MVCC、回滾段、一致性讀、鎖定讀

事務C

按照上圖的執行順序執行commit,其中事務C是自動提交事務的,不需要我們顯示的commit,事務A、B的輸出結果如下:

事務A:num=1
事務B:num=3

為什么是這樣輸出?

它的背后其實是:MVCC(多版本并發控制)、consistent read(一致性讀)、locking reads(鎖定讀)等MySQL數據庫底層知識。

1、MVCC

MySQL數據庫官網文檔是這樣來描述MVCC的:

日常學習MySQL底層之MVCC、回滾段、一致性讀、鎖定讀

 

官網鏈接:https://dev.mysql.com/doc/refman/8.0/en/innodb-multi-versioning.html

淘寶的數據庫內核月報中有提到(文末有文章鏈接):

多版本控制: 指的是一種提高并發的技術。最早的數據庫系統,只有讀讀之間可以并發,讀寫,寫讀,寫寫都要阻塞。引入多版本之后,只有寫寫之間相互阻塞,其他三種操作都可以并行,這樣大幅度提高了InnoDB的并發度。在內部實現中,與Postgres在數據行上實現多版本不同,InnoDB是在undolog中實現的,通過undolog可以找回數據的歷史版本。找回的數據歷史版本可以提供給用戶讀(按照隔離級別的定義,有些讀請求只能看到比較老的數據版本),也可以在回滾的時候覆蓋數據頁上的數據。在InnoDB內部中,會記錄一個全局的活躍讀寫事務數組,其主要用來判斷事務的可見性。

目前來看MVCC的實現依賴于:

  • 隱藏字段(DB_TRX_ID、DB_ROLL_PTR)
  • 回滾日志(undo log)
  • 一致性讀(consistent read)

你也可以這樣去理解MVCC:一個事務對數據進行更新操作時候,先把舊的數據放到一個單獨的地方(回滾段),其他事務讀取數據時候,根據DB_TRX_ID、DB_ROLL_PTR計算出undo log鏈中當前版本的數據。

2、一致性讀(consistent read)

繼續看官方文檔對consistent read的描述:

日常學習MySQL底層之MVCC、回滾段、一致性讀、鎖定讀

 

官網鏈接:https://dev.mysql.com/doc/refman/8.0/en/glossary.html#glos_consistent_read

直譯:

一個讀操作使用基于某個時刻的快照信息來顯示查詢結果,而不考慮同時運行的其他事務所執行的更改。如果查詢到的數據被其他事務所更改,則根據undo log中的內容來重建原始數據。這種技術避免了一些通過強制事務等待其他事務完成而降低并發性的鎖定問題。

  1. 在RR級別下,首次讀操作被執行時候創建一致性讀視圖ReadView,事務的后續讀都基于該視圖的數據;
  2. 在RC級別下,每一次讀操作都會創建一個最新的ReadView,因此每次select讀都可以獲取到當前已提交事務的最新數據;

一致性讀”是InnoDB引擎在RC和RR隔離級別下處理select語句的默認模式。因為一個“一致性讀”是不需要對它訪問的表設置任何的鎖,當對表執行“一致性讀”時候,其他會話可以自由的修改這些表。

另外:

讀未提交(read uncommitted)、串行化(serializable)是不需要依賴MVCC的,讀未提交直接每次都讀取當前數據的最新值即可。而serializable是直接采用加鎖的操作讓所有的事務都串行化執行,犧牲了并發能力。

一致性讀的實現方式:

  1. 每個事務啟動的瞬間,都會構建一個數組(m_ids),用來記錄目前所有“活躍事務”(事務啟動了,但是還沒提交)的 ID;
  2. 數組中的最小事務ID為低水位;
  3. 數組中的最大事務ID+1為高水位
  4. 數據版本可見性規則:當前數據某個版本是否可見,取決于當前數據的DB_TRX_ID以及這個一致性視圖數組中記錄的事務ID做對比來判斷:低水位以前的數據版本可見,高水位以后的數據版本不可見,低水位和高水位之間得查看當前數據版本的DB_TRX_ID是否存在數組中,若存在意味著事務未提交,不可見,若不存在意味著事務已提交,可見
日常學習MySQL底層之MVCC、回滾段、一致性讀、鎖定讀

 

那按照一致性讀的理解,事務B已經創建了自己的快照數據了,它的輸出應該是num = 2呀,為什么會是num=3?

可是如果不是num=3,那么已經提交的事務C的操作不就丟失了嗎?(產生丟失更新問題)

這里又涉及到一個知識點:

更新數據都是先讀后寫的,而這個讀,只能讀當前的值,稱為“當前讀”(current read)。

3、當前讀(current reads)

也叫做鎖定讀(locking reads)

日常學習MySQL底層之MVCC、回滾段、一致性讀、鎖定讀

 

官方文檔:https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html

InnoDB引擎支持兩種方式的鎖定讀以提供額外的安全性(MySQL 5.7版本):

# 讀鎖(S 鎖,共享鎖)
SELECT ... LOCK IN SHARE MODE;
# 寫鎖(X 鎖,排他鎖)
SELECT ... FOR UPDATE;

鎖定讀會在被讀取的數據上加一把共享鎖,其他事務可以讀取記錄,但是不可以修改記錄,直到當前事務提交。

鎖定讀驗證:

日常學習MySQL底層之MVCC、回滾段、一致性讀、鎖定讀

 

為什么要有鎖定讀?

如果你在一個事務中先查詢了一個數據,然后插入或者更新相關的數據,這個時候來了一個事務B同時更新或者刪除你要查詢的記錄,就會出現幻讀問題了。

這也是為什么MVCC不能完全解決幻讀的問題,而是需要MVCC+行鎖+間隙鎖(next-key lock)的方式。

4、事務A、B、C的執行流程

繼續看開頭的第一張圖:

日常學習MySQL底層之MVCC、回滾段、一致性讀、鎖定讀

 

start transaction with consistent snapshot;

這條SQL語句可以立即啟動事務,創建當前事務的一致性讀快照。效果等同于start transaction然后馬上執行select語句。

 

我們接下來看看文章開頭的三個事務對數據行的修改流程,按照步驟1~6的操作如下:

日常學習MySQL底層之MVCC、回滾段、一致性讀、鎖定讀

 

如果大家細致的查看上圖的三個事務的穿插執行流程,可以發現,A、B、C三個事務無論是commit還是rollback,都是可以最終得到正確的數據。

這就是InnoDB引擎下的多版本并發控制(MVCC)的實現原理。

總結以下幾個關鍵點:

  1. 每一個事務都會創建一個數據快照,快照創建的時機根據隔離級別的不同有所區別;
  2. 每一個事務都會生成一個全局唯一的DB_TRX_ID,用于標記當前版本;
  3. DB_ROLL_PTR是回滾指針的意思,結合DB_TRX_ID來最終確定我要拿到的數據;
  4. DB_TRX_ID、DB_ROLL_PTR、undo log這三個值來控制數據的版本;
  5. update、delete操作都是先讀后寫,這個讀屬于鎖定讀(當前讀)。

5、巨人的肩膀

  1. 《MySQL實戰45講》
  2. 《高性能MySQL 第二版》
  3. MySQL官網:https://dev.mysql.com/doc/refman/8.0/en/innodb-multi-versioning.html
  4. 淘寶數據庫內核月報 - 2017 / 12:http://mysql.taobao.org/monthly/2017/12/01/

最后,感謝大家能夠看到這里,也許這篇文章并不能讓你能夠徹底了解MVCC的工作原理,看完之后可能還會有很多疑問,歡迎大家在評論區多多討論,充分交流,共同學習。

分享到:
標簽:MySQL MVCC
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定