MySQL學(xué)習(xí)之日志系統(tǒng)

前面我們系統(tǒng)了解了一個查詢語句的執(zhí)行流程伐蒋,并介紹了執(zhí)行過程中涉及的處理模塊。相信你還記得顽素,一條查詢語句的執(zhí)行過程一般是經(jīng)過連接器咽弦、分析器、優(yōu)化器胁出、執(zhí)行器等功能模塊,最后到達(dá)存儲引擎段审。 那么一條更新語句的執(zhí)行流程又是怎么樣的呢? 有時候你聽DBA的同事說,MySQL可以恢復(fù)到半個月內(nèi)任意一秒的狀態(tài),有沒有產(chǎn)生過好奇,?這是怎么做到的呢? 我們帶著這兩個問題往下看:
(MySQL 邏輯架構(gòu)圖)

我們把MySQL的基本執(zhí)行鏈路在拿過來進(jìn)行看下,??可以確定的是,?查詢的那一套流程, 更新語句也會走一遍全蝶。

在一個表上進(jìn)行更新的時候,跟這個表有關(guān)的所有緩存,都會失效抑淫,這條語句會把表上的所有緩存結(jié)果都清空绷落,所以我們建議不查詢緩存的原因。

接下來分析器會知道這是一條更新語句始苇,如果更新的字段有索引砌烁,優(yōu)化器會采用這個字段的索引,執(zhí)行器具體負(fù)責(zé)執(zhí)行催式,找到這一行數(shù)據(jù)函喉,然后更新。

與查詢不一樣的是荣月,更新流程會有兩個重要的日志模塊管呵。redo log?(重做日志) 和 binlog (歸檔日志)。

重要的日志模塊 一哺窄、redo log

在講redo log 之前捐下,?我們要來回顧一篇文章《孔乙己》。

在這篇文章里萌业,有一個酒店掌柜坷襟,有一塊粉板,專門用來記錄客人賒賬的記錄生年。如果賒賬的人不多婴程,掌柜可以把姓名和金額記錄到粉板上。但是如果人多了晶框,粉板記不下了排抬,掌柜就要放下手頭的工作,記錄到專門的賬本上授段。

如果有人賒賬蹲蒲,掌柜一般有兩種做法:

????1、直接翻出賬本侵贵,進(jìn)行記錄賒賬人和金額届搁;

????2、先記錄到粉板窍育,在不忙的時候記錄到賬本卡睦。

在生意紅火的時候,掌柜會選擇后者漱抓,因為前者過于麻煩表锻,效率太低。

在MySQL中乞娄,MySQL的設(shè)計者們瞬逊,也采用了粉板的思路來提升效率显歧,而粉板與賬本的配合過程中,其實就是MySQL中的WAL技術(shù)(write-ahead-logging)确镊,關(guān)鍵點就是 先寫日志士骤,再寫磁盤。也就是先寫粉板蕾域,再寫賬本拷肌。

也就是說,當(dāng)一條更新語句過來時旨巷,InnoDB引擎會把記錄記錄到redo?log(粉板)中巨缘,并更新內(nèi)存,這個時候就算更新完成了契沫。InnoDB引擎會在合適的時候带猴,進(jìn)行更新到磁盤中。

redo log 的大小是固定的懈万,比如可以一組配置4個文件拴清,每個文件大小是1G,那么這個redo log 可以記錄4G会通。從頭開始寫口予,寫到末尾就又回到開頭循環(huán)寫,如下面這個圖所示涕侈。

(寫redo log(粉板)?示意圖?--圖引自 MySQL45講)

write pos 是當(dāng)前記錄的位置沪停,一邊寫一邊后移,寫到第 3 號文件末尾后就回到 0 號文件開頭裳涛。checkpoint 是當(dāng)前要擦除的位置木张,也是往后推移并且循環(huán)的,擦除記錄前要把記錄更新到數(shù)據(jù)文件端三。

write pos 和 checkpoint 中間空著的部分舷礼,就是可以寫入的部分,如果write pos 追上了 checkpoint 郊闯,代表寫滿了妻献,就需要停下擦除一部分,把checkpoint推進(jìn)一下团赁。

有了 redo log育拨,InnoDB 就可以保證即使數(shù)據(jù)庫發(fā)生異常重啟,之前提交的記錄都不會丟失欢摄,這個能力稱為 crash-safe熬丧。redo log 是屬于?InnoDB特有的日志。

二怀挠、binlog

我們之前學(xué)習(xí)知道锹引,MySQL有兩塊矗钟,一塊是server層唆香,一塊是引擎層嫌变。也知道,redo log?是InnoDB特有的日志躬它,server層也有自己的日志腾啥,就是binlog(歸檔日志)。

為什么會有兩份日志呢冯吓?

因為在最開始倘待,MySQL并沒有innodb引擎。MySQL自帶的是MyISAM组贺,但是 MyISAM 沒有 crash-safe 的能力凸舵,binlog 日志只能用于歸檔。而 InnoDB 是另一個公司以插件形式引入 MySQL 的失尖,既然只依靠 binlog 是沒有 crash-safe 能力的啊奄,所以 InnoDB 使用另外一套日志系統(tǒng)——也就是 redo log 來實現(xiàn) crash-safe 能力。

這兩種日志有以下三點不同掀潮。

?? ?1菇夸、redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 層實現(xiàn)的仪吧,所有引擎都可以使用庄新。

??? 2、redo log 是物理日志薯鼠,記錄的是“在某個數(shù)據(jù)頁上做了什么修改”择诈;binlog 是邏輯日志,記錄的是這個語句的原始邏輯出皇,比如“給 ID=2 這一行的 c 字段加 1 ”羞芍。

????3、redo log 是循環(huán)寫的恶迈,空間固定會用完涩金;binlog 是可以追加寫入的∠局伲“追加寫”是指 binlog 文件寫到一定大小后會切換到下一個步做,并不會覆蓋以前的日志。

有了對這兩個日志的一些概念性理解奈附,我們應(yīng)該能知道流程是如何進(jìn)行執(zhí)行的了全度。

update 語句的執(zhí)行流程圖??--圖引自 MySQL45

先找到引擎取出這一行,引擎通過B+ TREE找到這一行斥滤。如果這個數(shù)據(jù)頁本就在內(nèi)存将鸵,直接返回勉盅。否則從磁盤讀入內(nèi)存,然后返回顶掉。

執(zhí)行器拿到引擎給的數(shù)據(jù)草娜,做上邏輯操作,調(diào)用引擎接口寫入數(shù)據(jù)痒筒。

引擎將新數(shù)據(jù)更新到內(nèi)存宰闰,同時將這個操作記錄到redo log 中,此時redo log 處于 prepare狀態(tài)簿透。然后告知執(zhí)行器執(zhí)行完成移袍,可以提交(commit)事務(wù)。

執(zhí)行器生成這個操作的binlog老充,把binlog寫入磁盤葡盗。調(diào)用提交事務(wù)接口,把剛剛的binlog改成提交狀態(tài)啡浊。

二觅够、將redo log拆為prepare 和 commit?兩階段引發(fā)的思考

為什么要有兩階段提交啊虫啥?

這是為了讓兩份日志之間保持邏輯一致蔚约。要說明這個問題,就要想到我們開始的那個問題涂籽,怎么恢復(fù)到半個月內(nèi)任意一秒鐘的數(shù)據(jù)苹祟?。

因為binlog會記錄所有的邏輯操作评雌,并且采用?“追加寫”的方式树枫。如果DBA承諾可以恢復(fù),說明一定是備份了半個月的所有的binlog景东,同時系統(tǒng)會定期整庫備份砂轻。

1. 首先找個臨時庫,完全空的?

2. 找最近的一份全量備份,全量備份的時間點比如為202-01-31?00:00:00?

3. 從202-01-31?00:00:00開始找出到誤刪前的增量binlog日志,(需要將其誤操作記錄刪除, 不然還是會刪除掉之前的記錄)并執(zhí)行到臨時庫 這樣就保證了臨時庫和誤刪前的庫一致了。

說了這么多斤吐,那為什么需要兩階段提交呢搔涝?

由于 redo log 和 binlog 是兩個獨立的邏輯,如果不用兩階段提交和措,要么就是先寫完 redo log 再寫 binlog庄呈,或者采用反過來的順序。我們看看這兩種方式會有什么問題派阱。

1诬留、先寫 redo log 后寫 binlog假設(shè)在 redo log 寫完,binlog 還沒有寫完的時候文兑,MySQL 進(jìn)程異常重啟盒刚。由于我們前面說過的,redo log 寫完之后绿贞,系統(tǒng)即使崩潰因块,仍然能夠把數(shù)據(jù)恢復(fù)回來,所以恢復(fù)后這一行 c 的值是 1樟蠕。但是由于 binlog 沒寫完就 crash 了贮聂,這時候 binlog 里面就沒有記錄這個語句。因此寨辩,之后備份日志的時候,存起來的 binlog 里面就沒有這條語句歼冰。然后你會發(fā)現(xiàn)靡狞,如果需要用這個 binlog 來恢復(fù)臨時庫的話,由于這個語句的 binlog 丟失隔嫡,這個臨時庫就會少了這一次更新甸怕,恢復(fù)出來的這一行 c 的值就是 0,與原庫的值不同腮恩。

1梢杭、先寫 binlog 后寫 redo log。秸滴。如果在 binlog 寫完之后 crash武契,由于 redo log 還沒寫,崩潰恢復(fù)以后這個事務(wù)無效荡含,所以這一行 c 的值是 0咒唆。但是 binlog 里面已經(jīng)記錄了“把 c 從 0 改成 1”這個日志。所以释液,在之后用 binlog 來恢復(fù)的時候就多了一個事務(wù)出來全释,恢復(fù)出來的這一行 c 的值就是 1,與原庫的值不同误债。

可以看到浸船,如果不使用“兩階段提交”,那么數(shù)據(jù)庫的狀態(tài)就有可能和用它的日志恢復(fù)出來的庫的狀態(tài)不一致寝蹈。

簡單說李命,redo log 和 binlog 都可以用于表示事務(wù)的提交狀態(tài),而兩階段提交就是讓這兩個狀態(tài)保持邏輯上的一致躺盛。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末项戴,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子槽惫,更是在濱河造成了極大的恐慌周叮,老刑警劉巖辩撑,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異仿耽,居然都是意外死亡合冀,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門项贺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來君躺,“玉大人,你說我怎么就攤上這事开缎∽亟校” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵奕删,是天一觀的道長俺泣。 經(jīng)常有香客問我,道長完残,這世上最難降的妖魔是什么伏钠? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮谨设,結(jié)果婚禮上熟掂,老公的妹妹穿的比我還像新娘。我一直安慰自己扎拣,他們只是感情好赴肚,可當(dāng)我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著鹏秋,像睡著了一般尊蚁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上侣夷,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天横朋,我揣著相機(jī)與錄音,去河邊找鬼百拓。 笑死琴锭,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的衙传。 我是一名探鬼主播决帖,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蓖捶!你這毒婦竟也來了地回?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎刻像,沒想到半個月后畅买,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡细睡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年谷羞,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溜徙。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡湃缎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蠢壹,到底是詐尸還是另有隱情嗓违,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布知残,位于F島的核電站靠瞎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏求妹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一佳窑、第九天 我趴在偏房一處隱蔽的房頂上張望制恍。 院中可真熱鬧,春花似錦神凑、人聲如沸净神。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鹃唯。三九已至,卻和暖如春瓣喊,著一層夾襖步出監(jiān)牢的瞬間坡慌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工藻三, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留洪橘,地道東北人。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓棵帽,卻偏偏與公主長得像熄求,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子逗概,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容