成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

再有人問你什么是MVCC,就把這篇文章發給他!

開發 前端
MVCC,是Multiversion Concurrency Control的縮寫,翻譯過來是多版本并發控制,他也是一種并發控制的解決方案。

?一想到并發控制,很多人第一反應就是加鎖,的確,加鎖確實是解決并發問題最常見的方案。但是,其實除了加鎖以外,在數據庫領域,還有一種無鎖的方案可以來實現并發控制,那就是大名鼎鼎的MVCC。

MVCC,是Multiversion Concurrency Control的縮寫,翻譯過來是多版本并發控制,他也是一種并發控制的解決方案。    

我們知道,在數據庫中,對數據的操作主要有2中,分別是讀和寫,而在并發場景下,就可能出現以下三種情況:

  • 讀-讀并發
  • 讀-寫并發
  • 寫-寫并發

我們都知道,在沒有寫的情況下發讀-讀并?是不會出現問題的,而寫-寫并發?這種情況比較常用的就是通過加鎖的方式實現。那么,讀-寫并發則可以通過MVCC的機制解決。本文就來介紹下一下MySQL中MVCC的實現機制。

快照讀和當前讀

要想搞清楚MVCC的機制,最重要的一個概念那就是快照讀。

所謂快照讀,就是讀取的是快照數據,即快照生成的那一刻的數據,像我們常用的普通的SELECT語句在不加鎖情況下就是快照讀。如:

SELECT * FROM xx_table WHERE ...

和快照讀相對應的另外一個概念叫做當前讀,當前讀就是讀取最新數據,所以,加鎖的 SELECT,或者對數據進行增刪改都會進行當前讀,比如:

SELECT * FROM xx_table LOCK IN SHARE MODE;
SELECT * FROM xx_table FOR UPDATE;
INSERT INTO xx_table ...
DELETE FROM xx_table ...
UPDATE xx_table ...

可以說快照讀是MVCC實現的基礎,而當前讀是悲觀鎖實現的基礎。

那么,快照讀讀到的快照是從哪里讀到的的呢?換句話說,快照是存在哪里的呢?

Undo Log

undo log是Mysql中比較重要的事務日志之一,顧名思義,undo log是一種用于回退的日志,在事務沒提交之前,MySQL會先記錄更新前的數據到 undo log日志文件里面,當事務回滾時或者數據庫崩潰時,可以利用 undo log來進行回退。

這里面提到的存在undo log中的”更新前的數據”就是我們前面提到的快照。所以,這也是為什么很多人說UndoLog是MVCC實現的重要手段的原因。

那么,一條記錄在同一時刻可能有多個事務在執行,那么,undo log會有一條記錄的多個快照,那么在這一時刻發生SELECT要進行快照讀的時候,要讀哪個快照呢?

這就需要用到另外幾個信息了。

隱式字段

其實,數據庫中的每行記錄中,除了保存了我們自己定義的一些字段以外,還有一些重要的隱式字段的:

  • db_row_id:隱藏主鍵,如果我們沒有給這個表創建主鍵,那么會以這個字段來創建聚簇索引。
  • db_trx_id:對這條記錄做了最新一次修改的事務的ID
  • db_roll_ptr:回滾指針,指向這條記錄的上一個版本,其實他指向的就是Undo Log中的上一個版本的快照的地址。

因為每一次記錄變更之前都會先存儲一份快照到undo log中,那么這幾個隱式字段也會跟著記錄一起保存在undo log中,就這樣,每一個快照中都有有一個db_trx_id字段記錄了本次變更的事務ID,以及一個db_roll_ptr字段指向了上一個快照的地址。(db_trx_id和db_roll_ptr是重點,后面還會用到)

這樣,就形成了一個快照鏈表:

圖片

有了undo log,又有了幾個隱式字段,我們好像還是不知道具體應該讀取哪個快照,那怎么辦呢?

Read View

這時候就需要Read View 登場了,

Read View 主要來幫我們解決可見性的問題的, 即他會來告訴我們本次事務應該看到哪個快照,不應該看到哪個快照。

在 Read View 中有幾個重要的屬性:

  • trx_ids,系統當前未提交的事務 ID 的列表。
  • low_limit_id,未提交的事務中最大的事務 ID。
  • up_limit_id,未提交的事務中最小的事務 ID。
  • creator_trx_id,創建這個 Read View 的事務 ID。

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

那么,一個事務應該看到哪些快照,不應該看到哪些快照該如何判斷呢?

其實原則比較簡單,那就是事務ID大的事務應該能看到事務ID小的事務的變更結果,反之則不能!舉個例子:

假如當前有一個事務3想要對某條記錄進行一次快照讀的時候,他會先創建一個Read View,并且把當前所有還未提交的事務的信息記錄下來。比如up_limit_id = 2,low_limit_id = 5,trx_ids= [2,4,5],creator_trx_id= 6

圖片

我們前面說過,每一條記錄上都有一個隱式字段db_trx_id記錄對這條記錄做了最新一次修改的事務的ID,如db_trx_id = 3;

那么接下來,數據庫會拿這條記錄db_trx_id和Read View進行可見性比較。

如果db_trx_id<up_limit_id,則說明,在Read View中所有未提交的事務創建之前,db_trx_id = 3的這個事務就已經提交了,并且在這期間,并沒有新的事務提交。所有,這條記錄對當前事務就應該是可見的。

如果,db_trx_id>low_limit_id,則說明,db_trx_id = 3的這個事務是在Read View中所有未提交的事務創建之后才提交的,也就是說,在當前事務開啟之后,有別的事務修改了數據并作了提交。所以,這個記錄對于當前事務來說應該就是不可見的。(不可見怎么辦呢?后面講)

那么,還有另外一種情況,那就是up_limit_id > db_trx_id > low_limit_id,這種情況下,會再拿db_trx_id和Read View中的trx_ids進行逐一比較。

如果,db_trx_id在trx_ids列表中,那么表示在當前事務開啟時,并未提交的某個事務在修改數據之后提交了,那么這個記錄對于當前事務來說應該是不可見的。

如果,db_trx_id不在trx_ids列表中,那么表示的是在當前事務開啟之前,其他事務對數據進行修改并提交了,所有,這條記錄對當前事務就應該是可見的。

所以,當讀取一條記錄的時候,經過以上判斷,發現記錄對當前事務可見,那么就直接返回就行了。那么如果不可見怎么辦?沒錯,那就需要用到undo log了。

當數據的事務ID不符合Read View規則時候,那就需要從undo log里面獲取數據的歷史快照,然后數據快照的事務ID再來和Read View進行可見性比較,如果找到一條快照,則返回,找不到則返回空。

圖片

所以,總結一下,在InnoDB中,MVCC就是通過Read View + Undo Log來實現的,undo log中保存了歷史快照,而Read View 用來判斷具體哪一個快照是可見的。

MVCC和隔離級別

其實,根據不同的事務隔離級別,Read View的獲取時機是不同的,在RC下,一個事務中的每一次SELECT都會重新獲取一次Read View,而在RR下,一個事務中只在第一次SELECT的時候會獲取一次Read View。

所以,可重復讀這種事務隔離級別之下,因為有MVCC機制,就可以解決不可重復讀的問題,因為他只有在第一次SELECT的時候才會獲取一次Read View,天然不存在重復讀的問題了。

參考資料:

  • https://dev.mysql.com/doc/refman/5.7/en/innodb-undo-logs.html
  • https://time.geekbang.org/column/article/120351
  • https://blog.csdn.net/SnailMann/article/details/94724197
  • http://www.ekrvqnd.cn/article/641019.html
  • https://zhuanlan.zhihu.com/p/52977862
責任編輯:武曉燕 來源: Hollis
相關推薦

2018-08-07 16:01:32

synchronizevolatilefinal

2020-12-11 08:23:06

JavaMemory Mode內存模型

2018-07-03 14:54:25

Java內存模型

2018-12-07 09:31:52

分布式鎖服務框架分布式系統

2022-11-08 09:33:36

訂單系統電商

2021-02-22 13:32:19

MySQLSQL索引

2021-05-31 09:42:48

MySQL隔離級別

2022-05-23 09:41:27

分庫分表數據庫算法

2019-11-05 14:06:07

MySQLB+索引

2021-03-08 10:25:37

MySQL數據庫索引

2019-11-04 15:00:50

MySQL索引B+樹

2021-03-08 12:47:42

MySQL查詢數據

2022-10-21 16:39:56

JDK優化

2023-12-11 08:32:58

數據庫DruidDBA

2020-04-20 13:11:21

HashMap底層存儲

2020-04-28 09:15:58

HashMapJava數組

2019-09-19 14:03:32

B樹節點數據結構

2019-12-10 09:08:29

分布式開源RocketMQ

2019-04-15 14:40:46

消息隊列Java編程

2020-12-10 13:46:35

人工智能
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美性极品xxxx做受 | 最新av在线网址 | 蜜桃免费一区二区三区 | 精品国产欧美一区二区三区成人 | 国产成人精品一区二区三区 | 精品网站999 | 国产三级一区二区三区 | 中文字幕日韩欧美 | 欧美精品一区二区三区四区五区 | 日韩欧美电影在线 | 欧美一级二级三级视频 | 九九福利 | 午夜丰满少妇一级毛片 | 国内精品免费久久久久软件老师 | 成人精品鲁一区一区二区 | 一级毛片免费看 | 欧美精品久久久 | 国产高清精品一区二区三区 | 亚洲视频在线观看 | 国产成人精品一区二区三区在线观看 | 成人免费一区二区三区视频网站 | 日日操夜夜摸 | 亚洲高清视频在线 | 免费在线观看黄色av | 日韩精品激情 | 国产成人精品一区二区三区四区 | 国产激情第一页 | 久久高潮 | 日本精品视频 | 81精品国产乱码久久久久久 | 欧美日韩在线一区二区三区 | 成人精品一区二区户外勾搭野战 | 91偷拍精品一区二区三区 | 成人免费在线观看视频 | 久久久久91| 久久午夜国产精品www忘忧草 | 国产成人精品午夜视频免费 | 日本 欧美 国产 | 国产精品视频一二三区 | 国产成人精品一区二区三区视频 | 国产盗摄视频 |