自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

淺聊MVCC?你學(xué)會(huì)了嗎?

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

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

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

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

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

快照讀和當(dāng)前讀

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

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

SELECT * FROM xx_table WHERE ...

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

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

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

UndoLog

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

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

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

行記錄的隱式字段

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

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

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

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

圖片圖片

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

Read View

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

在 Read View 中具有幾個(gè)重要屬性:

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

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

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

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

圖片圖片

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

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

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

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

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

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

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

圖片圖片


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

MVCC和可重復(fù)讀

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

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

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

2021-07-01 19:22:33

腳本Shell參數(shù)

2023-01-10 08:43:15

定義DDD架構(gòu)

2024-02-04 00:00:00

Effect數(shù)據(jù)組件

2023-07-26 13:11:21

ChatGPT平臺(tái)工具

2024-01-19 08:25:38

死鎖Java通信

2024-01-02 12:05:26

Java并發(fā)編程

2023-08-01 12:51:18

WebGPT機(jī)器學(xué)習(xí)模型

2024-08-06 09:47:57

2022-07-08 09:27:48

CSSIFC模型

2023-01-30 09:01:54

圖表指南圖形化

2024-07-31 08:39:45

Git命令暫存區(qū)

2023-12-12 08:02:10

2023-10-10 11:04:11

Rust難點(diǎn)內(nèi)存

2022-07-13 08:16:49

RocketMQRPC日志

2023-01-31 08:02:18

2023-05-05 06:54:07

MySQL數(shù)據(jù)查詢

2023-08-26 21:34:28

Spring源碼自定義

2022-06-16 07:50:35

數(shù)據(jù)結(jié)構(gòu)鏈表

2022-12-06 07:53:33

MySQL索引B+樹

2023-07-30 22:29:51

BDDMockitoAssert測試
點(diǎn)贊
收藏

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