溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

InnoDB秒級(jí)快照原理是什么

發(fā)布時(shí)間:2021-10-09 17:17:46 來(lái)源:億速云 閱讀:153 作者:iii 欄目:數(shù)據(jù)庫(kù)

這篇文章主要介紹“InnoDB秒級(jí)快照原理是什么”,在日常操作中,相信很多人在InnoDB秒級(jí)快照原理是什么問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”InnoDB秒級(jí)快照原理是什么”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

InnoDB秒級(jí)快照原理是什么

開(kāi)始事務(wù)的兩種方式

需要注意的是:begin/start transaction 命令并不是一個(gè)事務(wù)的起點(diǎn),在執(zhí)行到它們之后的第一個(gè)操作InnoDB  表的語(yǔ)句,事務(wù)才真正啟動(dòng)。 如果你想要馬上啟動(dòng)一個(gè)事務(wù),可以使用transaction with consistent snapshot 這個(gè)命令!

第一種啟動(dòng)方式,一致性視圖是在第執(zhí)行第一個(gè)快照讀語(yǔ)句時(shí)創(chuàng)建的;

第二種啟動(dòng)方式,一致性視圖是在執(zhí)行 start transaction with consistent snapshot 時(shí)創(chuàng)建的;

事務(wù) C 沒(méi)有顯式地使用 begin/commit,表示這個(gè) update 語(yǔ)句本身就是一個(gè)事務(wù),語(yǔ)句完成的時(shí)候會(huì)自動(dòng)提交。事務(wù) B 在更新了行之后查詢  ; 事務(wù) A 在一個(gè)只讀事務(wù)中查詢,并且時(shí)間順序上是在事務(wù) B 的查詢之后。但是結(jié)果卻是:事務(wù) B 查到的 k 的值是 3,而事務(wù) A 查到的 k 的值是  1

InnoDB秒級(jí)快照原理是什么

按照我們想象的情況應(yīng)該是如下所示:

InnoDB秒級(jí)快照原理是什么

最終得到的結(jié)果是事務(wù)A查詢的結(jié)果為1,事務(wù)B查詢的結(jié)果是2,但是為什么事務(wù)B查詢后為3呢??

需要注意的是,在 MySQL 里,有兩個(gè)視圖的概念:

1、一個(gè)是view,它是一個(gè)用查詢語(yǔ)句定義的虛擬表,在調(diào)用的時(shí)候執(zhí)行查詢語(yǔ)句并生成結(jié)果。創(chuàng)建視圖的語(yǔ)法是 create view …  ,而它的查詢方法與表一樣。

2、另一個(gè)是 InnoDB 在實(shí)現(xiàn) MVCC(Multi-Version Concurrency Control,多版本并發(fā)控制)時(shí)用到的一致性讀視圖,即  consistent read view,用于支持 RC(Read Committed,讀提交)和 RR(Repeatable  Read,可重復(fù)讀)隔離級(jí)別的實(shí)現(xiàn)。

InnoDB創(chuàng)建秒級(jí)快照原理

本文的首圖即是MVCC的實(shí)現(xiàn)原理,在可重復(fù)讀隔離級(jí)別下,事務(wù)在啟動(dòng)的時(shí)候就”拍了個(gè)快照”。注意,這個(gè)快照是基于整庫(kù)的。如果一個(gè)庫(kù)有  100G,那么我啟動(dòng)一個(gè)事務(wù),MySQL就要拷貝 100G 的數(shù)據(jù)出來(lái),這個(gè)過(guò)程得多慢啊??墒瞧綍r(shí)的事務(wù)執(zhí)行起來(lái)很快啊,實(shí)際上,我們并不需要拷貝出這 100G  的數(shù)據(jù)。我們先來(lái)看看這個(gè)快照是怎么實(shí)現(xiàn)的:

InnoDB 里面每個(gè)事務(wù)有一個(gè)唯一的事務(wù) ID,叫作 transaction id。它是在事務(wù)開(kāi)始的時(shí)候向 InnoDB  的事務(wù)系統(tǒng)申請(qǐng)的,是按申請(qǐng)順序嚴(yán)格遞增的。而每行數(shù)據(jù)也都是有多個(gè)版本的。每次事務(wù)更新數(shù)據(jù)的時(shí)候,都會(huì)生成一個(gè)新的數(shù)據(jù)版本,并且把 transaction id  賦值給這個(gè)數(shù)據(jù)版本的事務(wù) ID,記為 row  trx_id。同時(shí),舊的數(shù)據(jù)版本要保留,并且在新的數(shù)據(jù)版本中,能夠有信息可以直接拿到它。也就是說(shuō),數(shù)據(jù)表中的一行記錄,其實(shí)可能有多個(gè)版本  (即row中的每個(gè)數(shù)據(jù)),每個(gè)版本有自己的 row trx_id。

如所示,就是一個(gè)記錄被多個(gè)事務(wù)連續(xù)更新后的狀態(tài)。

InnoDB秒級(jí)快照原理是什么

圖中的三個(gè)虛線箭頭,就是 undo log(回滾日志);而 V1、V2、V3 并不是物理上真實(shí)存在的,而是每次需要的時(shí)候根據(jù)當(dāng)前版本和 undo log  計(jì)算出來(lái)的。比如,需要 V2 的時(shí)候,就是通過(guò) V4 依次執(zhí)行 U3、U2 算出來(lái)。

按照可重復(fù)讀的定義,一個(gè)事務(wù)啟動(dòng)的時(shí)候,能夠看到所有已經(jīng)提交的事務(wù)結(jié)果。但是之后,這個(gè)事務(wù)執(zhí)行期間,其他事務(wù)的更新對(duì)它不可見(jiàn)。

因此,一個(gè)事務(wù)只需要在啟動(dòng)的時(shí)候聲明說(shuō),“以我啟動(dòng)的時(shí)刻為準(zhǔn),如果一個(gè)數(shù)據(jù)版本是在我啟動(dòng)之前生成的,就認(rèn);如果是我啟動(dòng)以后才生成的,我就不認(rèn),我必須要找到它的上一個(gè)版本”。如果是這個(gè)事務(wù)自己更新的數(shù)據(jù),它自己還是要認(rèn)的。

在實(shí)現(xiàn)上, InnoDB 為每個(gè)事務(wù)構(gòu)造了一個(gè)數(shù)組,用來(lái)保存這個(gè)事務(wù)啟動(dòng)瞬間,當(dāng)前正處于啟動(dòng)了但還沒(méi)提交的所有事務(wù)ID。數(shù)組里面事務(wù) ID  的最小值記為低水位,當(dāng)前系統(tǒng)里面已經(jīng)創(chuàng)建過(guò)的事務(wù) ID  的最大值加1記為高水位。這個(gè)視圖數(shù)組和高水位,就組成了當(dāng)前事務(wù)的一致性視圖(read-view)而數(shù)據(jù)版本的可見(jiàn)性規(guī)則,就是基于數(shù)據(jù)的 row trx_id  和這個(gè)一致性視圖的對(duì)比結(jié)果得到的。這個(gè)視圖數(shù)組把所有的 row trx_id 分成了幾種不同的情況:

InnoDB秒級(jí)快照原理是什么

這樣,對(duì)于當(dāng)前事務(wù)的啟動(dòng)瞬間來(lái)說(shuō),一個(gè)數(shù)據(jù)版本的 row trx_id,有以下幾種可能:

1、如果落在綠色部分,表示這個(gè)版本是已提交的事務(wù)或者是當(dāng)前事務(wù)自己生成的,這個(gè)數(shù)據(jù)是可見(jiàn)的;

2、如果落在紅色部分,表示這個(gè)版本是由將來(lái)啟動(dòng)的事務(wù)生成的,是肯定不可見(jiàn)的;

3、如果落在黃色部分,那就包括兩種情況

  • 若 row trx_id 在數(shù)組中,表示這個(gè)版本是由還沒(méi)提交的事務(wù)生成的,不可見(jiàn);

  • 若 row trx_id 不在數(shù)組中,表示這個(gè)版本是已經(jīng)提交了的事務(wù)生成的,可見(jiàn)。

重點(diǎn)要理解落在黃色部分的兩種情況,一條數(shù)據(jù)被多個(gè)事物更新(事務(wù)還未提交),那么肯定在數(shù)組中含有row  trx_id,即這個(gè)版本是由還沒(méi)提交的事務(wù)生成的

所以InnoDB如何秒級(jí)創(chuàng)建快照的呢?我的總結(jié)如下:

1、事務(wù)開(kāi)啟時(shí)InnoDB會(huì)賦給事務(wù)一個(gè)ID,為了方便我們直接叫做事務(wù)ID

2、表中每行數(shù)據(jù)有多個(gè)版本,A事務(wù)更新數(shù)據(jù)的時(shí)候,都會(huì)生成一個(gè)新的數(shù)據(jù)版本,并且把A事務(wù)的事務(wù)ID賦值給這個(gè)數(shù)據(jù)版本的事務(wù)ID

3、通過(guò)回滾日志來(lái)計(jì)算事務(wù)ID對(duì)應(yīng)的數(shù)據(jù)版本,比如A事務(wù)更新了  id=1的數(shù)據(jù)的value為1,那么就存在id=1那一條數(shù)據(jù)的新版本,(id=1,value=1)這一條數(shù)據(jù)對(duì)應(yīng)的事務(wù)ID就是A事務(wù)的事務(wù)ID

4、如果一個(gè)數(shù)據(jù)版本的事務(wù)ID落在黃色部分并且還在事務(wù)數(shù)組中就判定此數(shù)據(jù)版本是其他未提交事務(wù)對(duì)數(shù)據(jù)修改產(chǎn)生的數(shù)據(jù)新版本;如果一個(gè)數(shù)據(jù)版本的事務(wù)ID落在黃色部分并且不在自己的事務(wù)數(shù)組中,那么說(shuō)明事務(wù)已經(jīng)提交,是合法數(shù)據(jù)

所以InnoDB的秒級(jí)快照的創(chuàng)建能力的原理無(wú)非和Linux的AUFS文件系統(tǒng)如出一撤,那就是你只要改了某一條數(shù)據(jù),我就復(fù)制那一條讓你改,并且不會(huì)影響其他人的數(shù)據(jù):

InnoDB秒級(jí)快照原理是什么

都是”當(dāng)前讀”惹的禍

我們?cè)诿靼琢薎nnoDB如何實(shí)現(xiàn)的創(chuàng)建秒級(jí)快照的原理后,開(kāi)篇的疑惑其實(shí)很好解答:

我們不妨做如下假設(shè),事務(wù) A 開(kāi)始前,系統(tǒng)里面只有一個(gè)活躍事務(wù) ID 是 99;事務(wù) A、B、C 的版本號(hào)分別是  100、101、102,且當(dāng)前系統(tǒng)里只有這四個(gè)事務(wù);三個(gè)事務(wù)開(kāi)始前,(1,1)這一行數(shù)據(jù)的 row trx_id 是 90

這樣,事務(wù) A 的視圖數(shù)組就是 [99,100],事務(wù) B 的視圖數(shù)組是 [99,100,101],事務(wù) C 的視圖數(shù)組是  [99,100,101,102]。

InnoDB秒級(jí)快照原理是什么

這其實(shí)就很容易理解了,事務(wù)C發(fā)現(xiàn),此時(shí)的已開(kāi)啟事務(wù)但是未提交的有四個(gè)(99,100,101,102),由于其他事務(wù)還并未對(duì)id=1這條數(shù)據(jù)進(jìn)行修改,所以此時(shí)只有一個(gè)版本那就是(id=1,  k=1,事務(wù)ID=90),并且90號(hào)事務(wù)ID處于低水位,說(shuō)明事務(wù)ID為90的事務(wù)已經(jīng)提交了,數(shù)據(jù)有效,隨后事務(wù)C把k置為了2,并且提交了事務(wù),所以此時(shí)生成了新版本(id=1,k=2,事務(wù)ID為102)

最后A事務(wù)去查詢k的值,發(fā)現(xiàn)已經(jīng)有三個(gè)版本了,當(dāng)A事務(wù)看到最新版本(id=1,k=3,事務(wù)ID為101)的數(shù)據(jù)時(shí),發(fā)現(xiàn)101在高水位,不能讀到,接著讀到版本為(id=1,k=2,事務(wù)ID為102)時(shí)候同樣事務(wù)102也是高水位,不能讀到,繼續(xù)讀,讀到(id=1,k=1,事務(wù)ID為90)的版本的數(shù)據(jù),事務(wù)ID為90的事務(wù)處于低水位,數(shù)據(jù)時(shí)可見(jiàn)的,于是得到的數(shù)據(jù)依舊是(id=1,  k=1, 事務(wù)ID為90)的數(shù)據(jù)版本

問(wèn)題來(lái)了?事務(wù)B是如何看到事務(wù)C的修改結(jié)果的??對(duì)于事務(wù)B來(lái)說(shuō),事務(wù)C不是高水位嗎?按道理應(yīng)該不可見(jiàn)高水位事務(wù)的修改呀!!!

事務(wù) B 的視圖數(shù)組是先生成的,之后事務(wù) C 才提交,不是應(yīng)該看不見(jiàn) (1,2)嗎,怎么能算出 (1,3) 來(lái)?

InnoDB秒級(jí)快照原理是什么

是的,如果事務(wù) B 在更新之前查詢一次數(shù)據(jù),這個(gè)查詢返回的 k 的值確實(shí)是 1。但是,當(dāng)它要去更新數(shù)據(jù)的時(shí)候,就不能再在歷史版本上更新了,否則事務(wù) C  的更新就丟失了。因此,事務(wù) B 此時(shí)的 set k=k+1 是在(1,2)的基礎(chǔ)上進(jìn)行的操作。所以,這里就用到了這樣一條規(guī)則:

更新數(shù)據(jù)都是先讀后寫(xiě)的,而這個(gè)讀,只能讀當(dāng)前的值,稱為“當(dāng)前讀”(current read)。

因此,在更新的時(shí)候,當(dāng)前讀拿到的數(shù)據(jù)是 (1,2),更新后生成了新版本的數(shù)據(jù) (1,3),這個(gè)新版本的 row trx_id 是 101。所以,在執(zhí)行事務(wù)  B 查詢語(yǔ)句的時(shí)候,一看自己的版本號(hào)是 101,最新數(shù)據(jù)的版本號(hào)也是101,是自己的更新,可以直接使用,所以查詢得到的 k 的值是 3。

但是select的結(jié)果卻是1,所以我們隊(duì)開(kāi)始的例子稍做修改,讓更新的時(shí)候值不在是k=k+1,這樣就避免了當(dāng)前讀,所以下面的例子就是避免的當(dāng)前讀所產(chǎn)生的結(jié)果:

InnoDB秒級(jí)快照原理是什么

因?yàn)樵贛YSQL中:不能在同一表中查詢的數(shù)據(jù)作為同一表的更新數(shù)據(jù),所以我這里使用了臨時(shí)表

其實(shí),除了 update 語(yǔ)句外,select 語(yǔ)句如果加鎖,也是當(dāng)前讀。

現(xiàn)在假設(shè)事務(wù) C 不是馬上提交的,而是變成了下面的事務(wù) C’,會(huì)怎么樣呢?

InnoDB秒級(jí)快照原理是什么

事務(wù) C’的不同是,更新后并沒(méi)有馬上提交,在它提交前,事務(wù) B 的更新語(yǔ)句先發(fā)起了。前面說(shuō)過(guò)了,雖然事務(wù) C’還沒(méi)提交,但是 (1,2)  這個(gè)版本也已經(jīng)生成了,并且是當(dāng)前的最新版本。那么,事務(wù) B 的更新語(yǔ)句會(huì)怎么處理呢?。

事務(wù) C’沒(méi)提交,也就是說(shuō) (1,2) 這個(gè)版本上的寫(xiě)鎖還沒(méi)釋放。而事務(wù) B 是當(dāng)前讀,必須要讀最新版本,而且必須加鎖,因此就被鎖住了,必須等到事務(wù) C’  釋放這個(gè)鎖,才能繼續(xù)它的當(dāng)前讀。

InnoDB秒級(jí)快照原理是什么

到這里,我們把一致性讀、當(dāng)前讀和行鎖就串起來(lái)了。

可重復(fù)讀的實(shí)現(xiàn)

可重復(fù)讀的核心就是一致性讀(consistent  read);而事務(wù)更新數(shù)據(jù)的時(shí)候,只能用當(dāng)前讀。如果當(dāng)前的記錄的行鎖被其他事務(wù)占用的話,就需要進(jìn)入鎖等待。

而讀提交的邏輯和可重復(fù)讀的邏輯類似,它們最主要的區(qū)別是:在可重復(fù)讀隔離級(jí)別下,只需要在事務(wù)開(kāi)始的時(shí)候創(chuàng)建一致性視圖,之后事務(wù)里的其他查詢都共用這個(gè)一致性視圖;在讀提交隔離級(jí)別下,每一個(gè)語(yǔ)句執(zhí)行前都會(huì)重新算出一個(gè)新的視圖。

InnoDB 的行數(shù)據(jù)有多個(gè)版本,每個(gè)數(shù)據(jù)版本有自己的 row trx_id,每個(gè)事務(wù)或者語(yǔ)句有自己的一致性視圖。普通查詢語(yǔ)句是一致性讀,一致性讀會(huì)根據(jù)  row trx_id  和一致性視圖確定數(shù)據(jù)版本的可見(jiàn)性。對(duì)于可重復(fù)讀,查詢只承認(rèn)在事務(wù)啟動(dòng)前就已經(jīng)提交完成的數(shù)據(jù);對(duì)于讀提交,查詢只承認(rèn)在語(yǔ)句啟動(dòng)前就已經(jīng)提交完成的數(shù)據(jù);而當(dāng)前讀,總是讀取已經(jīng)提交完成的最新版本。

到此,關(guān)于“InnoDB秒級(jí)快照原理是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI