第75講:MySQL數據庫MVCC多版本并發控制核心概念以及底層原理

文章目錄

    • 1.當前讀與快照讀的基本概念
      • 1.1.當前讀的基本概念
      • 1.2.快照讀的基本概念
    • 2.什么是MVCC多版本并發控制
    • 3.MVCC多版本并發控制依賴的三個組件重要概念
      • 3.1.MySQL表中三個隱式字段的概念
      • 3.2.undo log日志以及版本鏈的概念
      • 3.3.ReadView讀視圖的概念
    • 4.MVCC實現多版本并發控制的原理
    • 5.不同隔離級別下MVCC實現并發控制的原理
      • 5.1.RC隔離級別下MVCC多版本并發控制的原理分析
      • 5.2.RR隔離級別下MVCC多版本并發控制的原理分析

1.當前讀與快照讀的基本概念

在MVCC多版本并發控制中,核心概念和原理是非常復雜的,我們先來搞清楚MVCC中常見名稱的基本概念,然后再來講解什么是MVCC以及MVCC的原理。

1.1.當前讀的基本概念

當前讀指的是在事務中,通過Select查詢語句讀取的數據記錄是當前表中最新版本的記錄,默認情況下,在事務中讀取表中的數據時,為了避免并發事務對我們讀取的數據進行修改,會對讀取的記錄加鎖,即使其他事務修改了表中的數據,我們讀取到的數據仍然是其他事務修改之前的數據。

即使在事務中,我們也想要讀取當前表中最新的數據記錄,而并不是進入事務時查詢到的數據,那么此時就需要用到當前讀的概念,突破事務一開始讀取數據的鎖,通過當前讀來讀取表中最新版本的數據記錄。

如何才能突破讀取表記錄加的鎖呢?很簡單只要觸發當前讀的機制,使當前的查詢語句進化成當前讀的行為,就可以讀到表中最新版本的數據,當事務中執行的SQL,如select lock in share mode、update、insert、delete、select...for update這些,產生了共享鎖和排它鎖,此時就會產生當前讀。

下面來演示一下當前讀的效果。

1.開啟一個事務然后查詢xscjb中的數據,看到小明的ywcj是100
mysql> begin;
mysql> select * from xscjb;
+----+--------+------+------+------+------+
| xh | xm     | ywcj | sxcj | yycj | pjcj |
+----+--------+------+------+------+------+
|  1 | 小明   |  100 |   75 |   93 | NULL |2.此時再開啟一個事務修改小明的ywcj并提交
mysql> begin;
mysql> update xscjb set ywcj = '999' where xm = '小明';
mysql> commit;3.此時第一個事務任然讀到的數據是當前事務進入時的數據狀態,并非是最新的數據4.如果想要讀取表中最新的數據,那么就需要通過產生共享鎖、排查鎖的方式讀取到
mysql> select * from xscjb lock in share mode;
+----+--------+------+------+------+------+
| xh | xm     | ywcj | sxcj | yycj | pjcj |
+----+--------+------+------+------+------+
|  1 | 小明   |  999 |   75 |   93 | NULL |

image-20220627215456560

1.2.快照讀的基本概念

快照讀指的是:開啟事務后第一次查詢數據的結果集,這個結果集就會被做成快照讀,只要還是在當前的事務中,即使數據被其他事務修改了,我們無論執行多少次查詢,依舊查詢到的是快照讀的數據。

如1.1中的所示,即使ywcj被其他事務修改了,在當前事務中讀到的仍然是舊數據,也就是快照讀的數據。

簡單的select產生的都是快照讀,快照讀取的是記錄數據的可見版本,也有可能是歷史數據,不加鎖是非阻塞讀。

在不同隔離級別下,快照讀也不同:

  • Read Committed:每次select查詢,都會生產新的快照讀。
  • Repeatable Read:開啟事務后第一個select查詢,就是快照讀的地方。
  • Serializable:快照讀退化成當前讀。

快照讀也保證了數據的可重復讀。

2.什么是MVCC多版本并發控制

MVCC全稱是Multi-Version Concurrency Control,多版本并發控制,MVCC可以維護一個數據的多個版本,使讀寫操作沒有沖突。

MVCC是一種并發控制的方法,有了MVCC的支持后,不再使用單純的行級鎖對數據庫中的并發進行控制,而是使用MVCC將數據庫中的行鎖與行的多個版本進行結合,只需要很小的開銷,就可以實現非鎖定讀,從而大大提高數據庫系統的并發性能。

并發控制也很好理解,有人通過事務讀取了表中的數據,同時也有人通過事務在表中寫入或修改了數據,就會導致多個人看到的數據是不一致的,通過并發控制的手段,使每個連接者,在某個瞬間看到的數據時一個快照,即使通過其他事務修改了表中的數據,對于讀者來說也是看不到的,從而保證數據的一致性。

MVCC實現的是讀寫不阻塞,讀寫互不影響,通俗一點來說,MVCC可以使用戶覺得數據庫對于同一條數據,面對多個事務并發情況下,有多個不同版本的數據所提供。

MVCC多版本并發控制通過一定的機制生成一個數據請求時間點內,一致性的數據內容,也就是快照,并且利用這個快照來提供一定級別的一致性讀取,使用戶讀寫數據互不影響。

MVCC實現原理依靠于三個部分:隱式字段、undo log日志、ReadView。

3.MVCC多版本并發控制依賴的三個組件重要概念

我們知道什么是MVCC之后,接下來就需要去探討MVCC多版本并發控制實現的原理了,再研究原理之前,先弄明白,MVCC依賴的隱式字段、undo log日志、ReadView是什么東西。

3.1.MySQL表中三個隱式字段的概念

當我們創建好一張數據表之后,除了表中所有的字段外,InnoDB存儲引擎還會添加上三個隱藏的字段。

  • DB_TRX_ID
    • 表中的數據時會被修改的,INSERT、UPDATE、DELETE這些語句默認情況下,一條就代表一個事務,這個字段就是來記錄最后一次修改本條數據的事務ID。
  • DB_ROLL_PTR
    • 該字段是指針,代表回滾指針,該字段值會記錄本條數據上次修改前的一個版本,每條數據被修改后都會在undo log中進行記錄,在undo log記錄的每條數據中都會有一個版本號,該字段就是來記錄本條數據上次修改前在undo log中的版本號,可以配合undo log日志進行數據的回滾。
  • DB_ROW_ID
    • 該字段可能會出現也可能不出現,主要取決于表中是否存在主鍵,如果表中沒有主鍵,該字段就會出現,通過自增的方式為每條數據記錄一個ID,主要是為聚集索引服務的。

我們查看一個有主鍵的表所包含的隱式字段,當表中有主鍵時,只會出現DB_TRX_ID和DB_TRX_ID隱式字段。

[root@k8s-master ~]# ibd2sdi /var/lib/mysql/db_1/xscjb.ibd | grep name"name": "xscjb","name": "xh","name": "xm","name": "ywcj","name": "sxcj","name": "yycj","name": "pjcj","name": "DB_TRX_ID",					#記錄事務ID的隱式字段"name": "DB_ROLL_PTR",					#記錄回滾指針版本的隱式字段"name": "PRIMARY","name": "idx_xscjb_ywcj","name": "db_1/xscjb","filename": "./db_1/xscjb.ibd",

我們查看一個沒有主鍵的表所包含的隱式字段,當表中沒有主鍵時,三個隱式字段都會出現。

[root@k8s-master ~]# ibd2sdi /var/lib/mysql/db_1/jszx_xgymjzxxb.ibd | grep name"name": "jszx_xgymjzxxb","name": "id","name": "bm","name": "name","name": "xb","name": "nl","name": "szd","name": "zjhm","name": "wd","name": "first_injection","name": "second_injection","name": "third_injection","name": "wjzymjtyy","name": "zhycjzymdsj","name": "DB_ROW_ID",				#記錄行ID的隱式字段"name": "DB_TRX_ID",				#記錄事務ID的隱式字段"name": "DB_ROLL_PTR",				#記錄回滾指針版本的隱式字段"name": "PRIMARY","name": "db_1/jszx_xgymjzxxb","filename": "./db_1/jszx_xgymjzxxb.ibd",

3.2.undo log日志以及版本鏈的概念

undo log是回滾日志,當數據庫中產生insert、update、delete操作時就會產生便于數據回滾的日志,該日志就是undo log。

undo log日志是可以被刪除的,當產生insert語句后,事務一旦提交,undo log中的insert語句就可以被立即刪除,因為undo log只會在回滾時用到,像update、delete語句則不會立即刪除,因為還有可能其他事務再讀取這些數據。

undo log日志是實現MVCC版本控制最核心的一點,undo log日志中的版本鏈為數據形成了一份不同內容版本的鏈,這些鏈都會記錄在undo log日志文件中。

下面我們通過幾幅圖來演示undo log日志中的版本鏈的概念。

有一張表的原始數據如下,表中只有一條記錄,DB_TRX_ID字段的值為1,因為是新表只有一條數據,那么對應的事務ID也就是1,DB_ROLL_PTR字段的值為NULL,新插入的數據沒有被更新過,因此該字段的值為null。

idagenameDB_TRX_IDDB_ROLL_PTR
3030A301null

目前有四個并發事務(事務1是插入了這條數據,從事務2開始)同時操作這張表中的數據,我們來觀察undo log會記錄什么。

(undo log中記錄的是sql語句,這里為了方便演示,以真實數據代替)

1)事務2:修改表中id為30的數據,將age的值修改為3,修改完成后提交事務。

如下圖所示,當事務2中的修改語句執行時,首先將舊數據記錄在undo log日志中,然后再去更新表中的記錄,并且更新表中的數據時,會將隱式字段DB_TRX_ID的值更新成事務2的ID,同時回滾指針字段DB_ROLL_PTR的值也會指向undo log中記錄的舊數據對應的版本號,用于將來回滾使用。

image-20220627225951095

2)事務3:修改表中id為30的數據,將name字段修改為A3,修改完成后提交事務。

首先也是將變更前的數據記錄到undo log日志文件中,此時的版本鏈不變,記錄好之后,開始修改表中的數據,同時會將本條數據的DB_TRX_ID字段值修改成最后一次事務的ID,DB_ROLL_PTR的值會修改成undo log中記錄的修改前的舊數據對應的版本號,此時鏈就發生了改變了,表中數據的DB_ROLL_PTR值指向了最新一次舊數據的版本號,那么undo log中最新一次舊數據表的版本號同樣也會指向它上一次舊數據對應的版本號。

新數據指向最新一次舊數據的版本號,最新一次舊數據指向上次舊數據的版本號。

image-20220627230354294

3)事務4:修改表中id為30的數據,將age字段修改為10,修改完成后提交事務。

此時版本鏈的編號和事務3基本一樣了,首先在undo log中記錄舊數據,然后修改新數據的內容,然后將DB_TRX_ID字段修改成最新事務的ID,將DB_ROLL_PTR指針指向上一次舊數據對應的版本號,undo log中的最新一次的舊數據,也會指向上一次舊數據對應的版本號。

image-20220627230758168

最終我們可以看到在undo log中已經形成版本鏈了,不同事務或者相同事務操作一條記錄時,會在undo log中為這條記錄生產版本鏈表,鏈表的頭部是最新的舊數據記錄,鏈表的底部是最早的舊數據記錄。

此刻我們的一條數據就對應了很多個不同版本的數據情況,那么如何來識別讀哪一個版本的數據呢?就需要去了解ReadView了。

3.3.ReadView讀視圖的概念

ReadView讀視圖:是SQL產生了快照讀時,生成一個ReadView作為MVCC讀取數據的依據,我們知道當產生快照讀時,讀到的幾乎都是歷史數據,并不是最新數據,在undo log中記錄的每一條舊數據記錄都是歷史數據,一條數據可能會對應很多個版本的歷史數據,那么快照讀在執行時究竟應該讀取哪一個版本的數據呢?其實就是靠ReadView讀視圖來決定的。

在ReadView中有四個字段來記錄不同類型事務的ID,并且這四個字段與undo log中的事務ID有相應的匹配規則,當滿足某一項規則時,就會讀取該規則對應的版本的歷史數據。

ReadView讀事務會依據以下四個字段判斷要讀取那一個版本的歷史數據:

  • m_ids:是一個集合,當前活躍的所有讀寫事務的事務ID都會記錄在這個ids集合中。

    • 活躍的事務就表示當前事務正在進行中,還沒有提交,只要事務沒有提交都會處于活躍的狀態。
  • min_trx_id:最小活躍事務ID。

    • 是基于m_ids集合內的所有活躍的事務ID,在這個集合中最小的活躍事務ID。
  • max_trx_id:預分配事務ID,不是當前活躍的事務集合中最大的事務ID,相當于一個預留的事務ID,一般都是當前事務ID+1的新事務ID。

  • creator_trx_id:ReadView創建者的事務ID,通常情況也是當前事務的事務ID。

當前數據中DB_TRX_ID字段對應的事務ID,如果比最小的活躍事務ID還要小,就表示DB_TRX_ID字段對應的事務ID是處于提交的狀態。如果DB_TRX_ID字段對應的事務ID比最小活躍事務ID還大,那么說明改事務可能也是活躍事務處于未提交的狀態。

有了讀取數據版本的依據之后,就需要有對應的規則來決定要讀取數據的哪個版本。

ReadView決定要讀取數據的哪個歷史版本時,是由undo log版本鏈中數據對應的事務ID與ReadView的四個字段中記錄的事務ID進行規則匹配,共有四種匹配規則,當匹配的結果滿足規則時,就會讀取規則對應的歷史版本數據。

undo log版本鏈中針對相同的數據可能會記錄很多條不同版本的數據,此時就會先拿表中當前的數據與ReadView規則進行匹配,如果滿足則讀取這個版本的數據,如果不滿足則再去undo log版本鏈中從上往下一次匹配每一條數據,當滿足ReadView規則時,則讀取對應版本的數據,

在匹配ReadView規則時,是從上往下依次進行規則匹配的,當滿足第一個規則時就讀取對應的版本數據,后面的規則將不會匹配。讀取數據肯定會被某一個規則所匹配。

ReadView讀取某個版本數據時的四種匹配規則:

表中的一條數據或者undo log版本鏈中的一條數據,每一條數據都稱為一個版本。匹配規則是先從表中的數據記錄開始匹配,如果表中數據不滿足規則時,再從undo log版本鏈中對于數據的多個版本,從上到下依次匹配,只要有一個版本滿足了規則,則會返回該版本的數據,不會再往下進行匹配。

  • 當trx_id == creator_trx_id

    • 當某個版本的數據記錄中DB_TRX_ID字段記錄的事務ID,與ReadView的creator_trx_id字段記錄的事務ID相同,那么就可以讀取這個版本中的數據。
    • 因為creator_trx_id字段的值記錄的是當前事務的ID,如果數據中的記錄最后一次操作的事務ID值與creator_trx_id字段的值相同,就表示是當前事務所修改的數據,因此它是可以讀取到最新版本的數據的。
  • 當trx_id < min_trx_id

    • 當某個版本的數據中記錄事務ID值,小于所有活躍事務中最小的事務ID值時,就可以讀取這個版本的數據。
    • 因為所有的活躍事務,不管ID是大還是小,都是活躍是未提交的事務,如果當前版本的數據事務ID與活躍的事務ID相等或者比它ID大,就說明這個版本的數據還有可能被其他的事務處理中,因此是不可以被訪問到的。只有當版本中數據的事務ID比所有活躍事務中最小的那個事務ID還要小,就表示該版本的數據沒有被事務使用了,已經是提交狀態了,因此就可以讀取這個版本的數據。
  • 當trx_id > max_trx_id

    • 當某個版本的數據中記錄事務ID值,大于預留的事務ID,那么就不可以讀取這個版本中的數據。
    • 如果當前版本中數據記錄的事務ID比預分配的事務ID要大,那么就說明這個版本的數據是在我們當前事務之后又開啟的新事務,數據在處理中,因此不可以讀取這個版本中的數據。
  • 當min_trx_id <= trx_id <= max_trx_id

    • 當某個版本的數據記錄中事務ID的值,大于最小活躍的事務ID值,也小于預留的事務ID值,也就是事務ID位于最小活躍事務ID和預留事務ID之間的ID,并且當前版本數據記錄中的事務ID值不在m_ids集合中,當滿足這個規則時,那么就可以讀取這個版本中的數據。
    • 這個規則相當于給了一個事務ID的范圍,最小事務ID—最大事務ID區間的事務ID,如果版本中數據的事務ID在這個范圍列表里,還需要看一下這個事務ID是不是活躍的事務ID,主要是在m_ids集合中查看,如果也不會活躍的ID,那么就允許讀取此版本的數據,否則將不允許。

在四種規則里,trx_id表示的是當前版本中數據對應的事務ID的值,要通過trx_id的值和ReadView四個字段對應的值,進行匹配,滿足相應規則時放行。

在不同的隔離級別下,生成ReadView的時機不同:

  • READ COMMITTED :在事務中每一次執行快照讀時都生成一個ReadView,每個ReadView中四個字段的值都是不同的。

  • REPEATABLE READ:僅在事務中第一次執行快照讀時生成ReadView,后續復用該ReadView。

4.MVCC實現多版本并發控制的原理

MVCC多版本并發控制實現的原理就是通過InnoDB表的隱藏字段、undo log版本鏈、ReadView讀視圖配合來實現。

1)首先在表中的數據都會有兩個主要的隱藏字段,一個是DB_TRX_ID記錄最后一次操作的事務ID,還有一個是DB_ROLL_PTR記錄版本指針用于回滾時使用。

2)在多并發事務的場景下,不同事務操作完表數據會都會將舊數據記錄在undo log,一條數據在undo log日志中可能會多個不同版本的數據,最終形成版本鏈表,不同版本的數據通過DB_ROLL_PTR字段值相互關聯。

3)當數據在undo log日志中形成版本鏈之后,MVCC就會通過ReadView讀視圖根據四個字段,與undo log版本鏈中不同版本中數據的事務ID進行規則匹配,當undo log版本鏈中從上到下的某一個版本數據滿足ReadView讀視圖中的規則,那么就讀取該版本對應的數據,并且不會再使用版本鏈中其他的版本數據再進行規則匹配。

簡單來說,MVCC實現多版本并發控制的原理,就是根據多事務在undo log中產生的多條舊數據形成的版本鏈表,將一條數據的多個版本中的事務ID與ReadView讀視圖中的四個字段所對應的事務ID進行規則匹配,如果這個版本的數據滿足ReadView四個字段的規則,那么就讀取這個版本的數據,如果不滿足規則,則用另一個版本的數據依次進行匹配,知道讀到滿足規則的數據。

多版本并發控制就是在多事務的場景下,讀取針對當前事務最合適的一個版本的數據,可能是新數據也可能是舊數據。

MVCC+鎖就實現了事務的隔離性,事務的一致性由ReadLog和UndoLog保證。

5.不同隔離級別下MVCC實現并發控制的原理

5.1.RC隔離級別下MVCC多版本并發控制的原理分析

在RC隔離級別下,每當執行的SQL是快照讀類型的,就會生成一個ReadView讀視圖,每次生成的ReadView讀視圖所對應的四個字段值都是不同的,在RC隔離級別下,每次快照讀讀取的版本數據可能也不相同。

下面我們通過一組事務來分析RC隔離級別下MVCC多版本并發控制的原理。

如下圖所示,在并發事務5中,查詢了兩次id為30的數據,由于當前的隔離級別是RC,所以每當產生一次快照讀都會生成一個ReadView,每次生成的ReadView四個字段值都不同,也就意味著兩次查詢相同數據的結果可能都不相同。兩次快照讀在獲取數據時,會根據所生成的ReadView四個字段的值與undolog版本鏈中的數據進行規則匹配,最終返回此次快照讀的數據。

image-20220629105505177

ReadView四個字段的獲取的值:m_ids記錄所有活躍事務的id號,分別是3/4/5對應事務3-事務5,min_trx_id記錄所有活躍事務中事務ID最小的值,那么也就是3,max_trx_id是預留的事務ID,當前事務ID是5,那么預留的事務ID就是6,creator_trx_id是生成readview的事務id,也就是5。

1)分析事務5中第一次快照讀的MVCC多版本并發控制的原理流程

如下圖所示,左側是快照讀可能會讀取的各個版本的數據,有表中的記錄,有undo log版本鏈中的記錄,右側是ReadView讀取版本數據的規則,并且將第一個快照讀產生的ReadView四個字段的值,帶入到了規則中,下面開始匹配。

image-20220629112449949

A)在匹配合適的版本數據時,首先匹配表中的記錄:image-20220629112802451也就是這條數據,這條數據對應的trx_id事務id是4,此時MVCC就會通過ReadView帶著這條數據去ReadView規則中進行匹配,在第一條規則中,trx_id為4不等于creator_trx_id(ID為5)的ID值,第二條規則中,trx_id=4大于了min_trx_id(ID為3),第三條規則中trx_id=4小于了max_trx_id(ID為6),第四條規則,trx_id=4位于min_trx_id(ID為3)與max_trx_id(ID為6)之間,但是該版本的數據事務ID是4,4位于m_ids(ID:3,4,5)集合中。

規則匹配結果為:1)不滿足 2)不滿足 3)不滿足 4)不滿足,該版本的數據都不滿足規則,此時就要去undo log版本鏈中匹配下一條數據了。

表中數據不滿足了,此時從undo log鏈中從上往下挨個匹配每個版本的數據,當某一個版本數據滿足規則后,下面的數據不再進行匹配。

B)然后匹配undo log版本鏈中最上面的數據:image-20220629113818189,該版本數據的trx_id事務ID為3,將trx_id=3帶入右側的ReadView版本鏈中進行匹配,在第一條規則中,trx_id為3不等于creator_trx_id(ID為5)的ID值,第二條規則中,trx_id=3等于了min_trx_id(ID為3),第三條規則中trx_id=3小于了max_trx_id(ID為6),第四條規則,trx_id=3位于min_trx_id(ID為3)與max_trx_id(ID為6)之間,但是該版本的數據事務ID是3,3位于m_ids(ID:3,4,5)集合中。

規則匹配結果為:1)不滿足 2)不滿足 3)不滿足 4)不滿足,該版本的數據都不滿足規則,此時繼續從undo log版本鏈中從上到下匹配下一條數據。

C)接著匹配undo log版本鏈中第二條版本數據:image-20220629114122695,該版本數據的trx_id事務ID為2,將trx_id=2帶入右側的ReadView版本鏈中進行匹配,在第一條規則中,trx_id為2不等于creator_trx_id(ID為5)的ID值,第二條規則中,trx_id=2小于min_trx_id(ID為3),該版本的數據滿足ReadView規則中的第二個規則,此時就會終止匹配,快照讀此時就會返回版本鏈中這個版本所對應的數據。

表中記錄、undo log版本鏈的數據從上往下依次匹配ReadView規則,當有一個版本的數據滿足規則后,就返回給快照讀獲取該版本的數據,這就是MVCC多版本并發情況下,分配給快照讀合適版本數據的原理和過程。

2)分析事務5中第二次快照讀的MVCC多版本并發控制的原理流程

在第一次快照讀時我們已經理解了MVCC是如何實現多版本并發控制的,根據表中記錄、undo log版本鏈中多個不同版本的數據,按照數據中的事務ID在ReadView規則中進行匹配,當滿足規則時,將該版本的數據返回給快照讀。

第二次快照度和第一次快照度大差不差,在第二次快照讀時,事務3提交了,那么在活躍的事務中就沒有事務3了,數據還是左側這么多個版本,右側的規則中為此次生成的ReadView四個字段帶入了新值。

image-20220629115002783

ReadView四個字段的獲取的值:m_ids記錄所有活躍事務的id號,分別是4/5對應事務4-事務5,min_trx_id記錄所有活躍事務中事務ID最小的值,那么也就是4,max_trx_id是預留的事務ID,當前事務ID是5,那么預留的事務ID就是6,creator_trx_id是生成readview的事務id,也就是5。

A)首先匹配表中的記錄:image-20220629112802451也就是這條數據,該版本數據的trx_id事務ID為4,將trx_id=3帶入右側的ReadView版本鏈中進行匹配,在第一條規則中,trx_id為4不等于creator_trx_id(ID為5)的ID值,第二條規則中,trx_id=4等于了min_trx_id(ID為4),第三條規則中trx_id=4小于了max_trx_id(ID為6),第四條規則,trx_id=4位于min_trx_id(ID為4)與max_trx_id(ID為6)之間,但是該版本的數據事務ID是4,4位于m_ids(ID:4,5)集合中。

規則匹配結果為:1)不滿足 2)不滿足 3)不滿足 4)不滿足,該版本的數據都不滿足規則,此時就要去undo log版本鏈中匹配下一條數據了。

B)然后匹配undo log版本鏈中最上面的數據:image-20220629113818189,該版本數據的trx_id事務ID為3,將trx_id=3帶入右側的ReadView版本鏈中進行匹配,在第一條規則中,trx_id為3不等于creator_trx_id(ID為5)的ID值,第二條規則中,trx_id=3小于min_trx_id(ID為4),該版本的數據滿足ReadView規則中的第二個規則,此時就會終止匹配,快照讀此時就會返回版本鏈中這個版本所對應的數據。

5.2.RR隔離級別下MVCC多版本并發控制的原理分析

在RR隔離級別下,只會在事務第一次執行快照讀時會生成一個ReadView讀視圖,后續快照讀都會復用這個ReadView,讀取的版本數據都是相同的,也就說明了RR隔離級別是可重復度。

下面我們通過一組事務來分析RR隔離級別下MVCC多版本并發控制的原理。

如下圖所示,在并發事務5中,查詢了兩次id為30的數據,由于當前的隔離級別是RR,所以當第一次產生快照讀會生成一個ReadView決定四個字段的值,后面再有快照讀執行時,就會復用第一次快照讀產生的ReadView,也就意味著每次快照度產生的結構都是一樣的。

image-20220629131209342

ReadView四個字段的獲取的值:m_ids記錄所有活躍事務的id號,分別是3/4/5對應事務3-事務5,min_trx_id記錄所有活躍事務中事務ID最小的值,那么也就是3,max_trx_id是預留的事務ID,當前事務ID是5,那么預留的事務ID就是6,creator_trx_id是生成readview的事務id,也就是5。

多個版本的數據在RR隔離級別下的規則匹配流程與RC隔離級別一致。

1)分析事務5中首次快照讀的MVCC多版本并發控制的原理流程

如下圖所示,左側是快照讀可能會讀取的各個版本的數據,有表中的記錄,有undo log版本鏈中的記錄,右側是ReadView讀取版本數據的規則,并且將第一個快照讀產生的ReadView四個字段的值,帶入到了規則中,下面開始匹配。

image-20220629112449949

A)首先匹配表中的記錄:image-20220629112802451也就是這條數據,這條數據對應的trx_id事務id是4,此時MVCC就會通過ReadView帶著這條數據去ReadView規則中進行匹配,在第一條規則中,trx_id為4不等于creator_trx_id(ID為5)的ID值,第二條規則中,trx_id=4大于了min_trx_id(ID為3),第三條規則中trx_id=4小于了max_trx_id(ID為6),第四條規則,trx_id=4位于min_trx_id(ID為3)與max_trx_id(ID為6)之間,但是該版本的數據事務ID是4,4位于m_ids(ID:3,4,5)集合中。

規則匹配結果為:1)不滿足 2)不滿足 3)不滿足 4)不滿足,該版本的數據都不滿足規則,此時就要去undo log版本鏈中匹配下一條數據了。

B)然后匹配undo log版本鏈中最上面的數據:image-20220629113818189,該版本數據的trx_id事務ID為3,將trx_id=3帶入右側的ReadView版本鏈中進行匹配,在第一條規則中,trx_id為3不等于creator_trx_id(ID為5)的ID值,第二條規則中,trx_id=3等于了min_trx_id(ID為3),第三條規則中trx_id=3小于了max_trx_id(ID為6),第四條規則,trx_id=3位于min_trx_id(ID為3)與max_trx_id(ID為6)之間,但是該版本的數據事務ID是3,3位于m_ids(ID:3,4,5)集合中。

規則匹配結果為:1)不滿足 2)不滿足 3)不滿足 4)不滿足,該版本的數據都不滿足規則,此時繼續從undo log版本鏈中從上到下匹配下一條數據。

C)接著匹配undo log版本鏈中第二條版本數據:image-20220629114122695,該版本數據的trx_id事務ID為2,將trx_id=2帶入右側的ReadView版本鏈中進行匹配,在第一條規則中,trx_id為2不等于creator_trx_id(ID為5)的ID值,第二條規則中,trx_id=2小于min_trx_id(ID為3),該版本的數據滿足ReadView規則中的第二個規則,此時就會終止匹配,快照讀此時就會返回版本鏈中這個版本所對應的數據。

在RR隔離級別下,首次快照讀讀的版本數據,在后續的快照讀中也會復用該數據,做到重復讀。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/207263.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/207263.shtml
英文地址,請注明出處:http://en.pswp.cn/news/207263.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【FPGA】Verilog:BCD 加法器的實現

0x00 XOR 運算在 2 的補碼加減法中的應用 2 的補碼加減法的特點是&#xff0c;當從某個數中減去負數時&#xff0c;將其轉換為正數的加法來計算&#xff0c;并將減去正數的情況轉換為負數的加法來計算&#xff0c;從而將所有減法運算轉換為加法運算。在這種情況下&#xff0c;…

電商使用在線客服系統有什么好處?

互聯網發展越來越快&#xff0c;電商這個板塊也越加成熟&#xff0c;消費者選擇在線購物時會對比平臺&#xff0c;貨比三家&#xff0c;這個時候電商提供高效便捷且貼心的消費者服務就顯得尤為重要了&#xff0c;在線客服系統作為電商企業與消費者溝通的重要工具&#xff0c;其…

SpringAMQP 快速入門

SpringAMQP 快速入門 1. 創建項目2. 快速入門2.2.1 消息發送2.2.2 消息接收 3. 交換機3.1 Fanout Exchange&#xff08;扇出交換機&#xff09;3.1.1 創建隊列與交換機3.1.2 消息接收3.1.3 消息發送 3.2 Direct Exchange&#xff08;直連交換機&#xff09;3.2.1 創建交換機與隊…

Validate 驗證規則詳解

前言: 以前小編發過一篇Validate 驗證規則 如何使用的&#xff0c;沒有去將Validate 驗證規則的原理應用場景&#xff0c;這篇文章來完善一下。 不知道如何使用的朋友可以點擊下面傳送門 傳送門 講解: Validate 驗證規則通常指的是在 Web 開發中&#xff0c;使用驗證器&…

【開源】基于Vue.js的智慧社區業務綜合平臺

文末獲取源碼&#xff0c;項目編號&#xff1a; S 077 。 \color{red}{文末獲取源碼&#xff0c;項目編號&#xff1a;S077。} 文末獲取源碼&#xff0c;項目編號&#xff1a;S077。 目錄 一、摘要1.1 項目介紹1.2 項目錄屏 二、功能模塊2.1 業務類型模塊2.2 基礎業務模塊2.3 預…

python使用conda管理多個環境

一、Anaconda簡介 Anaconda 是專門為了方便使用 Python 進行數據科學研究而建立的一組軟件包&#xff0c;涵蓋了數據科學領域常見的 Python 庫&#xff0c;并且自帶了專門用來解決軟件環境依賴問題的 conda 包管理系統。主要是提供了包管理與環境管理的功能&#xff0c;可以很方…

精選Axure原型設計模板,RP原型組件庫(PC端移動端元件庫及Axure函數及運算符說明)

好的原型組件會大大的提高產品經理的工作效率&#xff0c;現精選了一批Axure 8的原型設計模板&#xff0c;包含了原型設計的常用元素和AxureRP 8函數及運算符的說明文檔&#xff0c;及各種設備模板框架。 分享給大家可以共同學習&#xff0c;文末可下載完整原型組件包~&#x…

蘋果手機ios系統安裝了一個免簽應用書簽webclip描述文件該如何卸載?

隨著移動應用的普及&#xff0c;越來越多的用戶開始關注到蘋果免簽的應用。相比于需要通過 App Store 審核和簽名的應用&#xff0c;免簽應用無需經過蘋果的審核過程&#xff0c;可以直接安裝和使用。那么&#xff0c;蘋果免簽應用是如何制作的呢&#xff1f;本文將介紹制作蘋果…

K3cloud-計算成本分析DEmo

業務背景 用于分析各月計劃與實際物料及費用偏差。費用根據成本計算表分攤邏輯需要計算后按產線、車間、公司等費用掛的成本中心&#xff0c;按價值法進行均攤。此含稅價取最近一次采購價格&#xff0c;按月會發生變化。 代碼示例 –建立臨時表 CREATE TABLE #KD_CB ( [公司…

SQL進階 | CASE表達式

本文所有案例基于《SQL進階教程》實現。 概述 SQL中的CASE表達式是一種通用的條件表達式&#xff0c;類似于其他語言中的if/else語句。它用于在SQL語句中實現條件邏輯。CASE表達式以WHEN子句開始&#xff0c;后面跟著一個或多個WHEN條件&#xff0c;每個WHEN條件后面跟著一個TH…

C++相關閑碎記錄(3)

1、reference wrapper 例如聲明如下的模板&#xff1a; template <typename T> void foo(T val); 如果調用使用&#xff1a; int x; foo(std::ref(x)); T變成int&&#xff0c;而使用調用 int x; foo(std::cref(x)); T變成const int&。 這個特性被C標準庫用…

fijkplayer flutter 直播流播放

fijkplayer flutter 直播流播放 fijkplayer 是 ijkplayer 的 Flutter 封裝&#xff0c; 是一款支持 android 和 iOS 的 Flutter 媒體播放器插件&#xff0c; 由 ijkplayer 底層驅動。 通過紋理&#xff08;Texture&#xff09;接入播放器視頻渲染到 Flutter 中。 前言 目前使用…

設置單擊右鍵可以選擇用VS Code打開文件

設置單擊右鍵可以選擇用VS Code打開文件_通過code打開-CSDN博客

PostgreSQL 技術內幕(十二) CloudberryDB 并行化查詢之路

隨著數據驅動的應用日益增多&#xff0c;數據查詢和分析的量級和時效性要求也在不斷提升&#xff0c;對數據庫的查詢性能提出了更高的要求。為了滿足這一需求&#xff0c;數據庫引擎不斷經歷創新&#xff0c;其中并行執行引擎是性能提升的重要手段之一&#xff0c;逐漸成為數據…

sh腳本移動文件

內容&#xff1a;兩臺服務器&#xff0c;one 和 two ,在one的指定目錄下&#xff0c;找到指定結尾的文件&#xff0c;將這個文件移到two服務器的指定路徑下&#xff0c;同時將one的源文件 移到 其他目錄下。 #!/bin/bash# 指定源路徑 source_path"/u01/isi/75_files_te…

One-to-Few Label Assignment for End-to-End Dense Detection閱讀筆記

One-to-Few Label Assignment for End-to-End Dense Detection閱讀筆記 Abstract 一對一&#xff08;o2o&#xff09;標簽分配對基于變換器的端到端檢測起著關鍵作用&#xff0c;最近已經被引入到全卷積檢測器中&#xff0c;用于端到端密集檢測。然而&#xff0c;o2o可能因為…

[動態規劃及遞歸記憶搜索法]1.鋼條切割問題

摘要 本系列從6道經典的動態規劃題入手&#xff0c;去理解動態規劃的基本思路和想法&#xff0c;以及動態規劃和遞歸記憶搜索法存在的某些聯系&#xff0c;對于每道題目&#xff0c;我們將用兩種方法去實現&#xff0c;這里講解第一道題目&#xff0c;作個開頭。 前言 我們知…

elasticsearch 內網下如何以離線的方式上傳任意的huggingFace上的NLP模型(國內避坑指南)

es自2020年的8.x版本以來&#xff0c;就提供了機器學習的能力。我們可以使用es官方提供的工具eland&#xff0c;將hugging face上的NLP模型&#xff0c;上傳到es集群中。利用es的機器學習模塊&#xff0c;來運維部署管理模型。配合es的管道處理&#xff0c;來更加便捷的處理數據…

吳恩達《機器學習》12-1:優化目標

在機器學習的旅程中&#xff0c;我們已經接觸了多種學習算法。在監督學習中&#xff0c;選擇使用算法 A 還是算法 B 的重要性逐漸減弱&#xff0c;而更關鍵的是如何在應用這些算法時優化目標。這包括設計特征、選擇正則化參數等因素&#xff0c;這些在不同水平的實踐者之間可能…