最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

03 用一次數(shù)據(jù)更新流程,初步了解InnoDB存儲引擎的架構(gòu)設(shè)計

2023-06-10 17:49 作者:儒猿課堂  | 我要投稿

用一次數(shù)據(jù)更新流程,初步了解InnoDB存儲引擎的架構(gòu)設(shè)計

1、更新語句在MySQL中是如何執(zhí)行的?


之前我們已經(jīng)分析了MySQL架構(gòu)上的整體設(shè)計原理,現(xiàn)在對一條SQL語句從我們的系統(tǒng)層面發(fā)送到MySQL中,然后一步一步執(zhí)行這條SQL的流程,都有了一個整體的了解。


我們已經(jīng)知道了,MySQL最常用的就是InnoDB存儲引擎,那么我們今天借助一條更新語句的執(zhí)行,來初步的了解一下InnoDB存儲引擎的架構(gòu)設(shè)計。


首先假設(shè)我們有一條SQL語句是這樣的:


update users set name='xxx' where id=10


那么我們先想一下這條SQL語句是如何執(zhí)行的?


首先肯定是我們的系統(tǒng)通過一個數(shù)據(jù)庫連接發(fā)送到了MySQL上,然后肯定會經(jīng)過SQL接口、解析器、優(yōu)化器、執(zhí)行器幾個環(huán)節(jié),解析SQL語句,生成執(zhí)行計劃,接著去由執(zhí)行器負責(zé)這個計劃的執(zhí)行,調(diào)用InnoDB存儲引擎的接口去執(zhí)行。


所以先看下圖,大致還是會走下圖的這個流程

? ? ? ? ? ?

? ? ? ? ? ? ?

今天我們就來探索一下這個存儲引擎里的架構(gòu)設(shè)計,以及如何基于存儲引擎完成一條更新語句的執(zhí)行


2、InnoDB的重要內(nèi)存結(jié)構(gòu):緩沖池


InnoDB存儲引擎中有一個非常重要的放在內(nèi)存里的組件,就是緩沖池(Buffer Pool),這里面會緩存很多的數(shù)據(jù),以便于以后在查詢的時候,萬一你要是內(nèi)存緩沖池里有數(shù)據(jù),就可以不用去查磁盤了,我們看下圖。


? ? ? ? ? ?

所以當(dāng)我們的InnoDB存儲引擎要執(zhí)行更新語句的時候 ,比如對“id=10”這一行數(shù)據(jù),他其實會先將“id=10”這一行數(shù)據(jù)看看是否在緩沖池里,如果不在的話,那么會直接從磁盤里加載到緩沖池里來,而且接著還會對這行記錄加獨占鎖。


因為我們想一下,在我們更新“id=10”這一行數(shù)據(jù)的時候,肯定是不允許別人同時更新的,所以必須要對這行記錄加獨占鎖


至于鎖的詳細分析,我們后續(xù)也會有,大家不用著急,在這里先初步了解即可,我們看下面的圖

? ? ??

3、undo日志文件:如何讓你更新的數(shù)據(jù)可以回滾?


接著下一步,假設(shè)“id=10”這行數(shù)據(jù)的name原來是“zhangsan”,現(xiàn)在我們要更新為“xxx”,那么此時我們得先把要更新的原來的值“zhangsan”和“id=10”這些信息,寫入到undo日志文件中去。


其實稍微對數(shù)據(jù)庫 有一點了解的同學(xué)都應(yīng)該知道,如果我們執(zhí)行一個更新語句,要是他是在一個事務(wù)里的話,那么事務(wù)提交之前我們都是可以對數(shù)據(jù)進行回滾的,也就是把你更新為“xxx”的值回滾到之前的“zhangsan”去。


所以為了考慮到未來可能要回滾數(shù)據(jù)的需要,這里會把你更新前的值寫入undo日志文件,我們看下圖。

? ? ? ? ? ?

? ? ? ? ? ? ?

4、更新buffer pool中的緩存數(shù)據(jù)


當(dāng)我們把要更新的那行記錄從磁盤文件加載到緩沖池,同時對他加鎖之后,而且還把更新前的舊值寫入undo日志文件之后,我們就可以正式開始更新這行記錄了,更新的時候,先是會更新緩沖池中的記錄,此時這個數(shù)據(jù)就是臟數(shù)據(jù)了。


這里所謂的更新內(nèi)存緩沖池里的數(shù)據(jù),意思就是把內(nèi)存里的“id=10”這行數(shù)據(jù)的name字段修改為“xxx”


那么為什么說此時這行數(shù)據(jù)就是臟數(shù)據(jù)了呢?


因為這個時候磁盤上“id=10”這行數(shù)據(jù)的name字段還是“zhangsan”,但是內(nèi)存里這行數(shù)據(jù)已經(jīng)被修改了,所以就會叫他是臟數(shù)據(jù)。


我們看下圖,我同時把幾個步驟的序號標記出來了。

? ? ? ? ? ??

5、Redo Log Buffer:萬一系統(tǒng)宕機,如何避免數(shù)據(jù)丟失?


接著我們來思考一個問題,按照上圖的說明,現(xiàn)在已經(jīng)把內(nèi)存里的數(shù)據(jù)進行了修改,但是磁盤上的數(shù)據(jù)還沒修改


那么此時萬一MySQL所在的機器宕機了,必然會導(dǎo)致內(nèi)存里修改過的數(shù)據(jù)丟失,這可怎么辦呢?


這個時候,就必須要把對內(nèi)存所做的修改寫入到一個Redo Log Buffer里去,這也是內(nèi)存里的一個緩沖區(qū),是用來存放redo日志的


所謂的redo日志,就是記錄下來你對數(shù)據(jù)做了什么修改,比如對“id=10這行記錄修改了name字段的值為xxx”,這就是一個日志。


我們先看下圖的示意

? ? ? ? ? ?

? ??

這個redo日志其實是用來在MySQL突然宕機的時候,用來恢復(fù)你更新過的數(shù)據(jù)的,但是我們現(xiàn)在還沒法直接講解redo是如何使用的,畢竟現(xiàn)在redo日志還僅僅停留在內(nèi)存緩沖里


大家稍安勿躁,繼續(xù)往下看


6、如果還沒提交事務(wù),MySQL宕機了怎么辦?


這里我們假設(shè)每個人看專欄的人,都對MySQL的基本SQL語法、事務(wù)的基本概念以及索引的基本概念有一個基礎(chǔ)的了解,因為但凡一個后端工程師,要跟數(shù)據(jù)庫打交道,必然會跟這些概念有一定的了解。


所以我們都知道,其實在數(shù)據(jù)庫中,哪怕執(zhí)行一條SQL語句,其實也可以是一個獨立的事務(wù),只有當(dāng)你提交事務(wù)之后,SQL語句才算執(zhí)行結(jié)束。


所以這里我們都知道,到目前為止,其實還沒有提交事務(wù),那么此時如果MySQL崩潰,必然導(dǎo)致內(nèi)存里Buffer Pool中的修改過的數(shù)據(jù)都丟失,同時你寫入Redo Log Buffer中的redo日志也會丟失


我們看下圖

? ? ? ? ? ?

?? ? ? ? ? ?

那么此時數(shù)據(jù)丟失要緊嗎?


其實是不要緊的,因為你一條更新語句,沒提交事務(wù),就代表他沒執(zhí)行成功,此時MySQL宕機雖然導(dǎo)致內(nèi)存里的數(shù)據(jù)都丟失了,但是你會發(fā)現(xiàn),磁盤上的數(shù)據(jù)依然還停留在原樣子。


也就是說,“id=1”的那行數(shù)據(jù)的name字段的值還是老的值,“zhangsan”,所以此時你的這個事務(wù)就是執(zhí)行失敗了,沒能成功完成更新,你會收到一個數(shù)據(jù)庫的異常。然后當(dāng)mysql重啟之后,你會發(fā)現(xiàn)你的數(shù)據(jù)并沒有任何變化。


所以此時如果mysql宕機,不會有任何的問題。


7、提交事務(wù)的時候?qū)edo日志寫入磁盤中


接著我們想要提交一個事務(wù)了,此時就會根據(jù)一定的策略把redo日志從redo log buffer里刷入到磁盤文件里去。


此時這個策略是通過innodb_flush_log_at_trx_commit來配置的,他有幾個選項。


當(dāng)這個參數(shù)的值為0的時候,那么你提交事務(wù)的時候,不會把redo log buffer里的數(shù)據(jù)刷入磁盤文件的,此時可能你都提交事務(wù)了,結(jié)果mysql宕機了,然后此時內(nèi)存里的數(shù)據(jù)全部丟失。


相當(dāng)于你提交事務(wù)成功了,但是由于MySQL突然宕機,導(dǎo)致內(nèi)存中的數(shù)據(jù)和redo日志都丟失了,我們看下圖:

? ? ? ? ? ?

當(dāng)這個參數(shù)的值為1的時候,你提交事務(wù)的時候,就必須把redo log從內(nèi)存刷入到磁盤文件里去,只要事務(wù)提交成功,那么redo log就必然在磁盤里了,我們看下圖:

? ? ? ? ? ?

那么只要提交事務(wù)成功之后,redo日志一定在磁盤文件里,此時你肯定會有一條redo日志說了,“我此時對哪個數(shù)據(jù)做了一個什么修改,比如name字段修改為xxx了”。


然后哪怕此時buffer pool中更新過的數(shù)據(jù)還沒刷新到磁盤里去,此時內(nèi)存里的數(shù)據(jù)是已經(jīng)更新過的“name=xxx”,然后磁盤上的數(shù)據(jù)還是沒更新過的“name=zhangsan”。


我們看下圖,提交事務(wù)之后,可能處于的一個狀態(tài)。

? ? ? ? ? ?

? ? ? ? ? ??

此時如果說提交事務(wù)后處于上圖的狀態(tài),然后mysql系統(tǒng)突然崩潰了,此時會如何?會丟失數(shù)據(jù)嗎?


肯定不會啊,因為雖然內(nèi)存里的修改成name=xxx的數(shù)據(jù)會丟失,但是redo日志里已經(jīng)說了,對某某數(shù)據(jù)做了修改name=xxx。


所以此時mysql重啟之后,他可以根據(jù)redo日志去恢復(fù)之前做過的修改,我們看下圖。

? ? ? ? ? ?

? ? ? ? ? ? ?

最后來看看,如果innodb_flush_log_at_trx_commit參數(shù)的值是2呢?


他的意思就是,提交事務(wù)的時候,把redo日志寫入磁盤文件對應(yīng)的os cache緩存里去,而不是直接進入磁盤文件,可能1秒后才會把os cache里的數(shù)據(jù)寫入到磁盤文件里去。


這種模式下,你提交事務(wù)之后,redo log可能僅僅停留在os cache內(nèi)存緩存里,沒實際進入磁盤文件,萬一此時你要是機器宕機了,那么os cache里的redo log就會丟失,同樣會讓你感覺提交事務(wù)了,結(jié)果數(shù)據(jù)丟了,看下圖。

? ? ? ? ? ?

? ? ? ? ? ? ?

8、小思考題:三種redo日志刷盤策略到底選擇哪一種?


今天給大家留一個小的思考題,大家覺得在提交事務(wù)的時候,我們對redo日志的刷盤策略應(yīng)該選擇哪一種?每一種刷盤策略的優(yōu)缺點分別是什么?為什么?


End

專欄版權(quán)歸公眾號儒猿技術(shù)窩所有

未經(jīng)許可不得傳播,如有侵權(quán)將追究法律責(zé)任

03 用一次數(shù)據(jù)更新流程,初步了解InnoDB存儲引擎的架構(gòu)設(shè)計的評論 (共 條)

分享到微博請遵守國家法律
元氏县| 汝城县| 吉木乃县| 昌邑市| 鄂托克旗| 花垣县| 漳浦县| 海丰县| 兴国县| 梅州市| 武山县| 通渭县| 珠海市| 连城县| 疏勒县| 雷山县| 九江县| 寿阳县| 宁陕县| 遂溪县| 汉源县| 宿州市| 玉山县| 英山县| 涞水县| 正蓝旗| 荥经县| 桑日县| 钟山县| 印江| 博爱县| 寿阳县| 文水县| 钦州市| 恭城| 亳州市| 泾阳县| 敦化市| 沁源县| 资溪县| 介休市|