溫馨提示×

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

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

MySQL中寫(xiě)操作時(shí)保駕護(hù)航的三兄弟是什么

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

本篇內(nèi)容介紹了“MySQL中寫(xiě)操作時(shí)保駕護(hù)航的三兄弟是什么”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

MySQL中寫(xiě)操作時(shí)保駕護(hù)航的三兄弟是什么

- 思維導(dǎo)圖 -

兩階段提交

這個(gè)名詞你應(yīng)該聽(tīng)到過(guò)很多次了,在這里再介紹下這位老朋友。

所謂的兩階段提交,從字面意思來(lái)看應(yīng)該是有兩個(gè)步驟來(lái)進(jìn)行約束的。事實(shí)上也是如此。這兩個(gè)步驟中的主角就是我們今天要講的重要角色中的兩位:binlog 和  redo log。

提到兩階段提交,SQL 語(yǔ)句的執(zhí)行流程就繞不過(guò)去了。沒(méi)轍,雖然提了很多遍,但還得再拉出來(lái)溜溜。只不過(guò)這次的側(cè)重點(diǎn)和前面的會(huì)有些不同。

具體到操作流程上是這樣的:

當(dāng)執(zhí)行某個(gè)寫(xiě)操作的 SQL 時(shí),引擎將這行數(shù)據(jù)更新到內(nèi)存的同時(shí)把對(duì)應(yīng)的操作記錄到 redo log 里面,然后處于 prepare  狀態(tài)。并把完成信息告知給執(zhí)行器。

執(zhí)行器生成對(duì)應(yīng)操作的 binlog,并把 binlog 寫(xiě)入磁盤(pán)里。然后調(diào)用引擎的提交事務(wù)接口,變更 redo log 狀態(tài)為  commit,這樣操作就算完成了。

MySQL中寫(xiě)操作時(shí)保駕護(hù)航的三兄弟是什么

好了,知道了兩階段提交后,我們接下來(lái)看看這些日志文件的真面目。

重做日志(redo log)

首先出場(chǎng)的是位于存儲(chǔ)引擎層的 redo log,它是用來(lái)記錄在"數(shù)據(jù)頁(yè)做了什么修改"的物理日志文件。

WAL 技術(shù)

提到 redo log,WAL 技術(shù)必然是繞不過(guò)去的,全稱是 Write-Ahead  Logging。也就是在同步磁盤(pán)前先寫(xiě)日志,然后系統(tǒng)再根據(jù)一定的策略將日志里的記錄同步到磁盤(pán)里。

存在的必要性

從上邊的兩階段提交的過(guò)程里,我們可以看到 WAL 技術(shù)的使用場(chǎng)景。不知道你有沒(méi)有疑惑,為什么中間非要寫(xiě) redo  log,直接將更新結(jié)果同步到磁盤(pán)里不行嗎?傻孩子,同步到磁盤(pán)里就意味著每次寫(xiě)操作就得產(chǎn)生隨機(jī)寫(xiě)盤(pán)操作,速度得多慢啊。

機(jī)智的你可能會(huì)說(shuō)了,那我能不能一定的時(shí)間后從內(nèi)存再同步到磁盤(pán)里,這種方式不行嗎?來(lái),先給你個(gè)腦瓜崩,你想想,我服務(wù)重啟了,這些數(shù)據(jù)還在不?內(nèi)存是易失的,不知道什么異常情況就會(huì)導(dǎo)致數(shù)據(jù)丟失。所以這時(shí)候就需要一個(gè)能持久化的中間文件,起到"緩沖"的作用,并且寫(xiě)入速度還不慢。

那么 redo log 就應(yīng)運(yùn)而生了。雖然同樣存儲(chǔ)在磁盤(pán)上,但是順序?qū)懭朐谒俣壬喜⒉皇苡绊?疑惑的同學(xué)可以了解下磁盤(pán)的隨機(jī)與順序讀寫(xiě)的區(qū)別)。

當(dāng)然 redo log 除了能起到"延遲"同步磁盤(pán)文件的作用外,在數(shù)據(jù)庫(kù)服務(wù)器宕機(jī)時(shí),還可以用來(lái)恢復(fù)數(shù)據(jù)。

寫(xiě)入時(shí)機(jī)

談到寫(xiě)入時(shí)機(jī),是不是更疑惑了,難倒不是更新完內(nèi)存就寫(xiě)入 redo log 文件嗎?答案確實(shí)不是,因?yàn)橹虚g還有一個(gè) redo log buffer(內(nèi)存中)  。Mysql 每執(zhí)行一條語(yǔ)句,會(huì)先將記錄寫(xiě)入 redo log buffer,后續(xù)執(zhí)行 commit 操作時(shí)會(huì)以一定的時(shí)機(jī)寫(xiě)入到 redo log  文件(磁盤(pán)上)中。

值得注意的是,redo log buffer 里的數(shù)據(jù)是在執(zhí)行 commit 操作時(shí)寫(xiě)入到 redo log 文件中的。

至于寫(xiě)入的時(shí)機(jī),則由下面的參數(shù)來(lái)控制的:

MySQL中寫(xiě)操作時(shí)保駕護(hù)航的三兄弟是什么

MySQL中寫(xiě)操作時(shí)保駕護(hù)航的三兄弟是什么

MySQL中寫(xiě)操作時(shí)保駕護(hù)航的三兄弟是什么

(圖片源自網(wǎng)絡(luò))

寫(xiě)入方式

知道了寫(xiě)入時(shí)機(jī),這里簡(jiǎn)單介紹下寫(xiě)入的方式吧。在 Innodb 中,redo log 的大小是固定的,那么就只能是以循環(huán)的方式進(jìn)行寫(xiě)入了。假如當(dāng)前我有 4  個(gè)文件,從第一個(gè)文件開(kāi)始寫(xiě)入,直到最后一個(gè)文件寫(xiě)滿為止,再回到開(kāi)頭將數(shù)據(jù)同步至文件后擦除掉繼續(xù)寫(xiě)。

MySQL中寫(xiě)操作時(shí)保駕護(hù)航的三兄弟是什么

圖中的 write pos 表示當(dāng)前記錄的位置,隨著不斷寫(xiě)入逐漸后移。當(dāng)寫(xiě)到 ib_logfile_3號(hào)文件時(shí),整個(gè) redo log  就被寫(xiě)滿了。此時(shí)更新操作就會(huì)被阻塞。系統(tǒng)根據(jù) check point 標(biāo)記位來(lái)擦除掉一些記錄(當(dāng)然前提是把這些記錄同步至磁盤(pán))。

總得來(lái)看 redo log 的寫(xiě)入方式就是一個(gè)不斷寫(xiě)入,寫(xiě)滿后擦除,又寫(xiě)入的過(guò)程。

二進(jìn)制日志(binlog)

說(shuō)完了 redo log,我們?cè)賮?lái)看看另一個(gè)位于服務(wù)層的二進(jìn)制日志文件  binlog,這位大兄弟扮演的角色是存儲(chǔ)邏輯日志的,所謂的邏輯日志就是指修改了什么,都會(huì)記錄其中。

例如:對(duì) id = 1 的字段進(jìn)行更新操作。

當(dāng)然除了記錄操作過(guò)程外,它還有支持主從同步及數(shù)據(jù)異?;謴?fù)的能力。

寫(xiě)入模式

binlog 中有三種寫(xiě)入模式,我們分別來(lái)看下有什么不同及對(duì)應(yīng)的優(yōu)缺點(diǎn):

MySQL中寫(xiě)操作時(shí)保駕護(hù)航的三兄弟是什么

(圖片源自網(wǎng)絡(luò))

寫(xiě)入方式

與 redo log 循環(huán)寫(xiě)不同的是, binlog 采用追加的方式寫(xiě)入,當(dāng)一個(gè)文件寫(xiě)到一定大小后就會(huì)切換到另一個(gè)。

與 redo log 的關(guān)聯(lián)

在上面的兩階段提交里我們有提到過(guò)在寫(xiě)入binlog 后會(huì)調(diào)用引擎的提交事務(wù)接口,變更 redo log 狀態(tài)為  commit。那么它是如何找到對(duì)應(yīng)的記錄,或者換句話說(shuō),它們兩者是怎么關(guān)聯(lián)起來(lái)的呢?

答案是通過(guò)一個(gè)共同的字段 XID,不僅在事務(wù)提交時(shí),在崩潰恢復(fù)的時(shí)候如果遇到僅寫(xiě)入 prepare 而沒(méi)有 commit 的 redo log,也可以通過(guò)  XID 去尋找對(duì)應(yīng)的事務(wù)。

回顧下寫(xiě)流程

到這里我們有必要回顧下寫(xiě)流程的操作,以更新某個(gè)字段為例:

MySQL中寫(xiě)操作時(shí)保駕護(hù)航的三兄弟是什么

回滾日志(undo log)

到這里,你可能會(huì)疑惑了,通篇里哪有 undo log 的影子,你個(gè)渣男!

別急,來(lái)了!

根據(jù)字面意思,你應(yīng)該能猜出來(lái)它是干啥的?;貪L嘛,也就是給你一次后悔的機(jī)會(huì)。在進(jìn)行數(shù)據(jù)修改時(shí),同時(shí)記錄 undo  log,即同時(shí)記錄相反操作的邏輯日志。你可以理解為操作 update 的時(shí)候,寫(xiě)一條對(duì)應(yīng)相反的 update 記錄,操作 delete 的時(shí)候,寫(xiě)一條對(duì)應(yīng)的  insert 記錄。

當(dāng)事務(wù)回滾時(shí)。從 undo log 中讀取到對(duì)應(yīng)的邏輯記錄就可以進(jìn)行回滾操作了。

總結(jié)

兩階段提交

  • 兩階段提交過(guò)程中,更新內(nèi)存的同時(shí)把對(duì)應(yīng)操作記錄到 redo log 中,并把生成的binlog 寫(xiě)入磁盤(pán)后提交事務(wù)。

重做日志

  • redo log  是位于存儲(chǔ)引擎層的物理日志,用來(lái)記錄在“數(shù)據(jù)頁(yè)做了什么修改”的物理日志文件。采用循環(huán)寫(xiě)的方式,記錄數(shù)據(jù)被修改后的樣子。同時(shí)還提供數(shù)據(jù)恢復(fù)的能力。

二進(jìn)制日志

  • binlog是位于服務(wù)層的邏輯日志,用來(lái)記錄“對(duì)數(shù)據(jù)做了什么修改”的日志文件。與 redo log  不同的是,可以一直進(jìn)行追加寫(xiě)入。同時(shí)還提供主從同步及數(shù)據(jù)異?;謴?fù)的能力。

回滾日志

  • 在數(shù)據(jù)修改時(shí),同時(shí)記錄 undo log,可以確保在事務(wù)回滾操作時(shí)進(jìn)行數(shù)據(jù)還原。

“MySQL中寫(xiě)操作時(shí)保駕護(hù)航的三兄弟是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(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