04 借著更新語句在InnoDB存儲引擎中的執(zhí)行流程,聊聊binlog是什么?

借著更新語句在InnoDB存儲引擎中的執(zhí)行流程,聊聊binlog是什么?
1、上一講思考題解答:redo日志刷盤策略的選擇建議
先給大家解釋一下上一講的思考題,我給大家的一個建議,其實對于redo日志的三種刷盤策略,我們通常建議是設(shè)置為1
也就是說,提交事務(wù)的時候,redo日志必須是刷入磁盤文件里的。
這樣可以嚴格的保證提交事務(wù)之后,數(shù)據(jù)是絕對不會丟失的,因為有redo日志在磁盤文件里可以恢復(fù)你做的所有修改。
如果要是選擇0的話,可能你提交事務(wù)之后,mysql宕機,那么此時redo日志沒有刷盤,導(dǎo)致內(nèi)存里的redo日志丟失,你提交的事務(wù)更新的數(shù)據(jù)就丟失了;
如果要是選擇2的話,如果機器宕機,雖然之前提交事務(wù)的時候,redo日志進入os cache了,但是還沒進入磁盤文件,此時機器宕機還是會導(dǎo)致os cache里的redo日志丟失。
所以對于數(shù)據(jù)庫這樣嚴格的系統(tǒng)而言,一般建議redo日志刷盤策略設(shè)置為1,保證事務(wù)提交之后,數(shù)據(jù)絕對不能丟失。
2、MySQL binlog到底是什么東西?
接著我們來看看MySQL binlog到底是個什么東西?
實際上我們之前說的redo log,他是一種偏向物理性質(zhì)的重做日志,因為他里面記錄的是類似這樣的東西,“對哪個數(shù)據(jù)頁中的什么記錄,做了個什么修改”。
而且redo log本身是屬于InnoDB存儲引擎特有的一個東西。
而binlog叫做歸檔日志,他里面記錄的是偏向于邏輯性的日志,類似于“對users表中的id=10的一行數(shù)據(jù)做了更新操作,更新以后的值是什么”
binlog不是InnoDB存儲引擎特有的日志文件,是屬于mysql server自己的日志文件。
3、提交事務(wù)的時候,同時會寫入binlog
所以其實我們上一講講到,在我們提交事務(wù)的時候,會把redo log日志寫入磁盤文件中去。然后其實在提交事務(wù)的時候,我們同時還會把這次更新對應(yīng)的binlog日志寫入到磁盤文件中去,如下圖所示。
? ? ? ? ??

? ? ? ? ? ? ?
大家可以在這個圖里看到一些變動,就是我把跟InnoDB存儲引擎進行交互的組件加入了之前提過的執(zhí)行器這個組件,他會負責(zé)跟InnoDB進行交互,包括從磁盤里加載數(shù)據(jù)到Buffer Pool中進行緩存,包括寫入undo日志,包括更新Buffer Pool里的數(shù)據(jù),以及寫入redo log buffer,redo log刷入磁盤,寫binlog,等等。
實際上,執(zhí)行器是非常核心的一個組件,負責(zé)跟存儲引擎配合完成一個SQL語句在磁盤與內(nèi)存層面的全部數(shù)據(jù)更新操作。
而且我們在上圖可以看到,我把一次更新語句的執(zhí)行,拆分為了兩個階段,上圖中的1、2、3、4幾個步驟,其實本質(zhì)是你執(zhí)行這個更新語句的時候干的事。
然后上圖中的5和6兩個步驟,是從你提交事務(wù)開始的,屬于提交事務(wù)的階段了。
4、binlog日志的刷盤策略分析
對于binlog日志,其實也有不同的刷盤策略,有一個sync_binlog參數(shù)可以控制binlog的刷盤策略,他的默認值是0,此時你把binlog寫入磁盤的時候,其實不是直接進入磁盤文件,而是進入os cache內(nèi)存緩存。
所以跟之前分析的一樣,如果此時機器宕機,那么你在os cache里的binlog日志是會丟失的,我們看下圖的示意
? ? ? ? ? ?

? ? ? ? ? ? ?
如果要是把sync_binlog參數(shù)設(shè)置為1的話,那么此時會強制在提交事務(wù)的時候,把binlog直接寫入到磁盤文件里去,那么這樣提交事務(wù)之后,哪怕機器宕機,磁盤上的binlog是不會丟失的,如下圖所示
? ? ? ? ? ?

? ? ? ? ? ??
5、基于binlog和redo log完成事務(wù)的提交
當(dāng)我們把binlog寫入磁盤文件之后,接著就會完成最終的事務(wù)提交,此時會把本次更新對應(yīng)的binlog文件名稱和這次更新的binlog日志在文件里的位置,都寫入到redo log日志文件里去,同時在redo log日志文件里寫入一個commit標記。
在完成這個事情之后,才算最終完成了事務(wù)的提交,我們看下圖的示意。
? ? ? ? ? ?

? ? ? ? ? ? ?
6、最后一步在redo日志中寫入commit標記的意義是什么?
這時候肯定有同學(xué)會問了,最后在redo日志中寫入commit標記有什么意義呢?
說白了,他其實是用來保持redo log日志與binlog日志一致的。
我們來舉個例子,假設(shè)我們在提交事務(wù)的時候,一共有上圖中的5、6、7三個步驟,必須是三個步驟都執(zhí)行完畢,才算是提交了事務(wù)。那么在我們剛完成步驟5的時候,也就是redo log剛刷入磁盤文件的時候,mysql宕機了,此時怎么辦?
這個時候因為沒有最終的事務(wù)commit標記在redo日志里,所以此次事務(wù)可以判定為不成功。不會說redo日志文件里有這次更新的日志,但是binlog日志文件里沒有這次更新的日志,不會出現(xiàn)數(shù)據(jù)不一致的問題。
如果要是完成步驟6的時候,也就是binlog寫入磁盤了,此時mysql宕機了,怎么辦?
同理,因為沒有redo log中的最終commit標記,因此此時事務(wù)提交也是失敗的。
必須是在redo log中寫入最終的事務(wù)commit標記了,然后此時事務(wù)提交成功,而且redo log里有本次更新對應(yīng)的日志,binlog里也有本次更新對應(yīng)的日志 ,redo log和binlog完全是一致的。
7、后臺IO線程隨機將內(nèi)存更新后的臟數(shù)據(jù)刷回磁盤
現(xiàn)在我們假設(shè)已經(jīng)提交事務(wù)了,此時一次更新“update users set name='xxx' where id=10”,他已經(jīng)把內(nèi)存里的buffer pool中的緩存數(shù)據(jù)更新了,同時磁盤里有redo日志和binlog日志,都記錄了把我們指定的“id=10”這行數(shù)據(jù)修改了“name='xxx'”。
此時我們會思考一個問題了,但是這個時候磁盤上的數(shù)據(jù)文件里的“id=10”這行數(shù)據(jù)的name字段還是等于zhangsan這個舊的值啊!
所以MySQL有一個后臺的IO線程,會在之后某個時間里,隨機的把內(nèi)存buffer pool中的修改后的臟數(shù)據(jù)給刷回到磁盤上的數(shù)據(jù)文件里去,我們看下圖:
? ? ? ? ??

? ? ? ? ? ? ?
當(dāng)上圖中的IO線程把buffer pool里的修改后的臟數(shù)據(jù)刷回磁盤的之后,磁盤上的數(shù)據(jù)才會跟內(nèi)存里一樣,都是name=xxx這個修改以后的值了!
在你IO線程把臟數(shù)據(jù)刷回磁盤之前,哪怕mysql宕機崩潰也沒關(guān)系,因為重啟之后,會根據(jù)redo日志恢復(fù)之前提交事務(wù)做過的修改到內(nèi)存里去,就是id=10的數(shù)據(jù)的name修改為了xxx,然后等適當(dāng)時機,IO線程自然還是會把這個修改后的數(shù)據(jù)刷到磁盤上的數(shù)據(jù)文件里去的
8、基于更新數(shù)據(jù)的流程,總結(jié)一下InnoDB存儲引擎的架構(gòu)原理
大家通過一次更新數(shù)據(jù)的流程,就可以清晰地看到,InnoDB存儲引擎主要就是包含了一些buffer pool、redo log buffer等內(nèi)存里的緩存數(shù)據(jù),同時還包含了一些undo日志文件,redo日志文件等東西,同時mysql server自己還有binlog日志文件。
在你執(zhí)行更新的時候,每條SQL語句,都會對應(yīng)修改buffer pool里的緩存數(shù)據(jù)、寫undo日志、寫redo log buffer幾個步驟;
但是當(dāng)你提交事務(wù)的時候,一定會把redo log刷入磁盤,binlog刷入磁盤,完成redo log中的事務(wù)commit標記;最后后臺的IO線程會隨機的把buffer pool里的臟數(shù)據(jù)刷入磁盤里去。
9、思考題:執(zhí)行更新操作的時候,為什么不能執(zhí)行修改磁盤上的數(shù)據(jù)?
好了,今天的文章接近尾聲,咱們再來思考一個問題:
為什么MySQL在更新數(shù)據(jù)的時候,要大費周章的搞這么多事情,包括buffer pool、redo log、undo log、binlog、事務(wù)提交、臟數(shù)據(jù)。引入了一大堆的概念,有復(fù)雜的流程和步驟。
為什么他反而最關(guān)鍵的修改磁盤里的數(shù)據(jù),要通過IO線程不定時的去執(zhí)行?
為什么他不干脆直接就每次執(zhí)行SQL語句,直接就更新磁盤里的數(shù)據(jù)得了?
End
專欄版權(quán)歸公眾號儒猿技術(shù)窩所有
未經(jīng)許可不得傳播,如有侵權(quán)將追究法律責(zé)任