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

關(guān)于MVCC,你知道多少?

數(shù)據(jù)庫
眾所周知,在讀取操作時沒有寫入操作的情況下,并發(fā)讀取不會引發(fā)問題;而寫入操作并發(fā)時,常常會通過加鎖的方式來處理。而針對讀取-寫入并發(fā)的場景,則可通過MVCC機制來解決。

MVCC,即多版本并發(fā)控制(Multiversion Concurrency Control),類似于數(shù)據(jù)庫鎖,是一種優(yōu)雅的并發(fā)控制方案。

我們了解,在數(shù)據(jù)庫環(huán)境中,數(shù)據(jù)操作主要包括讀取和寫入兩種操作,在并發(fā)情境下,可能出現(xiàn)以下三種情況:

  • 讀-讀并發(fā)
  • 讀-寫并發(fā)
  • 寫-寫并發(fā)

眾所周知,在讀取操作時沒有寫入操作的情況下,并發(fā)讀取不會引發(fā)問題;而寫入操作并發(fā)時,常常會通過加鎖的方式來處理。而針對讀取-寫入并發(fā)的場景,則可通過MVCC機制來解決。

快照讀和當前讀

要深入了解MVCC機制,其中最關(guān)鍵的一個概念就是快照讀。

所謂快照讀,即讀取快照數(shù)據(jù),即在生成快照時刻的數(shù)據(jù)。比如我們常用的普通SELECT語句在無鎖情況下就屬于快照讀。例如:

SELECT * FROM xx_table WHERE ...

與快照讀相對應(yīng)的另一個概念是當前讀,當前讀即獲取最新的數(shù)據(jù)。因此,加鎖的SELECT操作或進行數(shù)據(jù)的增刪改都屬于當前讀。例如:

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實現(xiàn)的基礎(chǔ),而當前讀則是悲觀鎖實現(xiàn)的基礎(chǔ)。

快照讀所讀取的快照數(shù)據(jù)來自于何處?換言之,這些快照數(shù)據(jù)存儲在何處?

UndoLog

undo log是 MySQL 中一種重要的事務(wù)日志之一。顧名思義,undo log 是用于回滾操作的日志。在事務(wù)提交之前,MySQL會將更新前的數(shù)據(jù)記錄到 undo log 日志文件中。當需要回滾事務(wù)或者發(fā)生數(shù)據(jù)庫崩潰時,可以通過 undo log 進行數(shù)據(jù)回退。

在這個過程中提到的 "更新前的數(shù)據(jù)" 存儲在undo log中,即我們之前提及的快照。因此,這正是許多人認為 Undo Log 是實現(xiàn) MVCC 的重要工具的原因之一。

在同一時刻,一條記錄可能會被多個事務(wù)操作。因此,undo log 可能會包含一條記錄的多個快照。當需要進行快照讀取時,就要考慮應(yīng)該讀取哪個快照。這時候就需要利用其他相關(guān)信息來做出決定。

行記錄的隱式字段

實際上,在數(shù)據(jù)庫的每一行記錄中,除了保存我們自定義的字段之外,還包含一些重要的隱式字段:

  • db_row_id:隱式主鍵。如果表沒有創(chuàng)建主鍵,將使用該字段創(chuàng)建聚簇索引。
  • db_trx_id:最后一次修改該記錄的事務(wù)ID。
  • db_roll_ptr:回滾指針,指向記錄的上一個版本,在本質(zhì)上指向Undo Log中的前一個版本的快照地址。

由于每次記錄更改之前都會先將一個快照存儲到undo log中,這些隱式字段也會與記錄一起保存在undo log中。因此,每個快照中都包含一個db_trx_id字段,表示最后一次修改該記錄的事務(wù)ID,以及一個db_roll_ptr字段,指向前一個快照的地址。(db_trx_id和db_roll_ptr是重點,將在后續(xù)中用到)

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

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

Read View

此時,Read View 登場,它的主要作用是解決可見性問題,即確定當前事務(wù)應(yīng)該查看哪個快照,而不應(yīng)查看哪個快照。

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

  • trx_ids:系統(tǒng)當前未提交的事務(wù)ID列表。
  • low_limit_id:應(yīng)分配給下一個事務(wù)的ID值。
  • up_limit_id:未提交事務(wù)中最小的事務(wù)ID。
  • creator_trx_id:創(chuàng)建該 Read View 的事務(wù)ID。

每次啟動一個事務(wù),都會獲得一個遞增的事務(wù)ID。通過ID的大小,我們可以確定事務(wù)的時間順序。

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

假設(shè)當前存在一個事務(wù)3想要進行快照讀取某條記錄,它會首先創(chuàng)建一個Read View,并記錄所有當前未提交事務(wù)的信息。例如,up_limit_id = 2,low_limit_id = 5,trx_ids= [2,4,5],creator_trx_id= 3

前文提到,每條記錄都包含一個隱式字段db_trx_id,記錄對該記錄進行最新修改的事務(wù)ID,例如db_trx_id = 3;

接下來,數(shù)據(jù)庫將檢查此記錄的db_trx_id與Read View進行可見性比較。

  • 若db_trx_id < up_limit_id,則意味著在Read View中所有未提交事務(wù)創(chuàng)建之前,事務(wù)ID為3的操作已經(jīng)提交,并在此期間沒有新的提交。因此,對當前事務(wù)而言,此記錄應(yīng)該是可見的。
  • 若db_trx_id > low_limit_id,則表示事務(wù)ID為3的操作是在Read View中所有未提交事務(wù)創(chuàng)建之后才提交的,也就是在當前事務(wù)開啟之后,有其他事務(wù)修改了數(shù)據(jù)并提交。因此,這條記錄對當前事務(wù)來說是不可見的。(不可見時的處理將在后文討論)

另一種情況是,up_limit_id < db_trx_id < low_limit_id。在此情況下,將db_trx_id與Read View中的trx_ids逐一比較。

  • 若db_trx_id在trx_ids列表中,表示在當前事務(wù)開啟時,某些未提交事務(wù)對數(shù)據(jù)進行了更改并提交,因此,對當前事務(wù)來說,此記錄應(yīng)該是不可見的。
  • 若db_trx_id不在trx_ids列表中,表示在當前事務(wù)開啟之前,其他事務(wù)對數(shù)據(jù)進行了修改并提交,所以對當前事務(wù)來說,該記錄是可見的。

因此,在讀取記錄時,經(jīng)過上述判斷,若記錄對當前事務(wù)可見,則直接返回。若不可見,則需要利用undo log。

當數(shù)據(jù)的事務(wù)ID與Read View規(guī)則不符時,需要從undo log中獲取數(shù)據(jù)的歷史快照,然后使用數(shù)據(jù)快照的事務(wù)ID與Read View進行可見性比較。如果找到一條快照,則返回數(shù)據(jù);否則,返回空。

因此,在InnoDB中,MVCC機制通過Read View和Undo Log相結(jié)合來實現(xiàn)。Undo Log保存了歷史快照,而Read View則確定了哪一個具體的快照對當前操作是可見的。

MVCC和可重復(fù)讀

根據(jù)不同的事務(wù)隔離級別,在InnoDB中,獲取Read View的時機有所不同。在可重復(fù)讀隔離級別下,每次查詢都會重新獲取一次Read View,而在讀已提交隔離級別下,只有在事務(wù)的第一次查詢時獲取一次Read View。

因此,在可重復(fù)讀隔離級別下,由于MVCC機制的存在,能夠有效解決不可重復(fù)讀的問題。因為在可重復(fù)讀隔離級別中,只在第一次查詢時獲取一次Read View,從而天然消除了可能導(dǎo)致重讀問題的可能性。

責(zé)任編輯:趙寧寧 來源: 碼上遇見你
相關(guān)推薦

2022-03-23 15:36:13

數(shù)字化轉(zhuǎn)型數(shù)據(jù)治理企業(yè)

2023-08-28 07:39:49

線程調(diào)度基本單位

2025-04-01 08:45:00

2022-04-02 14:51:58

數(shù)據(jù)中心數(shù)據(jù)安全物聯(lián)網(wǎng)

2024-04-16 16:20:46

2017-05-02 17:22:48

2022-08-11 08:46:23

索引數(shù)據(jù)結(jié)構(gòu)

2022-08-03 08:48:45

測試時間功能

2022-06-10 09:00:53

前端項目個JSON

2023-05-08 00:12:59

2023-08-02 08:14:33

監(jiān)控MTS性能

2021-04-27 07:52:18

跳槽數(shù)據(jù)分析

2023-09-07 10:26:50

接口測試自動化測試

2020-12-10 09:00:00

開發(fā).NET工具

2023-12-24 12:56:36

協(xié)程

2023-09-18 08:56:57

StringJava

2021-07-26 23:57:48

Vuex模塊項目

2024-09-26 14:48:35

SpringAOP范式

2024-10-28 12:46:22

點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 成人h视频在线观看 | 欧美日韩不卡合集视频 | 欧美一区二区大片 | 精品国产欧美一区二区 | 爱爱视频日本 | 日韩电影一区二区三区 | 天天射天天操天天干 | 欧美a∨| 久久综合狠狠综合久久综合88 | 国产在线高清 | 日本精品一区二区三区在线观看视频 | 成人黄色在线观看 | 97国产精品 | 久久国产精品免费一区二区三区 | 黄网站免费在线 | 日韩成人高清 | 天天干亚洲 | 成人影音 | 国产99久久精品一区二区永久免费 | 麻豆精品国产免费 | 91在线视频免费观看 | 在线视频一区二区 | 欧美色图综合网 | 在线看片网站 | 色橹橹欧美在线观看视频高清 | 中文字幕久久久 | 成人免费视频网站在线观看 | 91久久精品国产91久久 | 福利一区二区 | 韩日中文字幕 | 欧美久久久久久 | 国产成人福利在线观看 | 午夜影院网站 | 在线不卡一区 | 亚洲视频在线观看 | 亚洲高清在线免费观看 | 在线日韩| 久久精品久久久 | 高清18麻豆 | 精品国产视频在线观看 | 91在线视频 |