Redo log是什么?
MySQL數(shù)據(jù)庫作為現(xiàn)在互聯(lián)網(wǎng)公司內(nèi)最流行的關(guān)系型數(shù)據(jù)庫贫悄,相信大家都有工作中使用過园骆。InnoDB是MySQL里最為常用的一種存儲引擎寺晌,主要面向在線事務(wù)處理(OLTP)的應(yīng)用。今天就讓我們來探究一下InnoDB是如何一步一步實現(xiàn)事務(wù)的祖能,這次我們先講事務(wù)實現(xiàn)的redo log蟆沫。
首先我們先明確一下InnoDB的修改數(shù)據(jù)的基本流程籽暇,當(dāng)我們想要修改DB上某一行數(shù)據(jù)的時候,InnoDB是把數(shù)據(jù)從磁盤讀取到內(nèi)存的緩沖池上進行修改饭庞。這個時候數(shù)據(jù)在內(nèi)存中被修改戒悠,與磁盤中相比就存在了差異,我們稱這種有差異的數(shù)據(jù)為臟頁舟山。InnoDB對臟頁的處理不是每次生成臟頁就將臟頁刷新回磁盤绸狐,這樣會產(chǎn)生海量的IO操作,嚴重影響InnoDB的處理性能累盗。對于此寒矿,InnoDB有一套完善的處理策略,與我們這次主題關(guān)系不大若债,表過不提符相。既然臟頁與磁盤中的數(shù)據(jù)存在差異,那么如果在這期間DB出現(xiàn)故障就會造成數(shù)據(jù)的丟失蠢琳。為了解決這個問題啊终,redo log就應(yīng)運而生了。
Redo log工作原理
在講Redo log工作原理之前挪凑,先來學(xué)習(xí)一下MySQL的一些基礎(chǔ):
一孕索、日志類型
redo log在數(shù)據(jù)庫重啟恢復(fù)的時候被使用,因為其屬于物理日志的特性躏碳,恢復(fù)速度遠快于邏輯日志。而我們經(jīng)常使用的binlog就屬于典型的邏輯日志。
二菇绵、 checkpoint
坦白來講checkpoint本身是比較復(fù)雜的肄渗,checkpoint所做的事就是把臟頁給刷新回磁盤。所以咬最,當(dāng)DB重啟恢復(fù)時翎嫡,只需要恢復(fù)checkpoint之后的數(shù)據(jù)。這樣就能大大縮短恢復(fù)時間永乌。當(dāng)然checkpoint還有其他的作用惑申。
三、 LSN(Log Sequence Number)
LSN實際上就是InnoDB使用的一個版本標(biāo)記的計數(shù)翅雏,它是一個單調(diào)遞增的值圈驼。數(shù)據(jù)頁和redo log都有各自的LSN。我們可以根據(jù)數(shù)據(jù)頁中的LSN值和redo log中LSN的值判斷需要恢復(fù)的redo log的位置和大小望几。
四绩脆、 工作原理
好的,現(xiàn)在我們來看看redo log的工作原理橄抹。說白了靴迫,redo log就是存儲了數(shù)據(jù)被修改后的值。當(dāng)我們提交一個事務(wù)時楼誓,InnoDB會先去把要修改的數(shù)據(jù)寫入日志玉锌,然后再去修改緩沖池里面的真正數(shù)據(jù)頁。
我們著重看看redo log是怎么一步步寫入磁盤的疟羹。redo log本身也由兩部分所構(gòu)成即重做日志緩沖(redo log buffer)和重做日志文件(redo log file)主守。這樣的設(shè)計同樣也是為了調(diào)和內(nèi)存與磁盤的速度差異。InnoDB寫入磁盤的策略可以通過innodb_flush_log_at_trx_commit
這個參數(shù)來控制阁猜。
當(dāng)該值為1時丸逸,當(dāng)然是最安全的,但是數(shù)據(jù)庫性能會受一定影響剃袍。
為0時性能較好黄刚,但是會丟失掉master thread還沒刷新進磁盤部分的數(shù)據(jù)。
這里我想簡單介紹一下master thread民效,這是InnoDB一個在后臺運行的主線程憔维,從名字就能看出這個線程相當(dāng)?shù)闹匾K龅闹饕ぷ靼ǖ幌抻冢核⑿氯罩揪彌_畏邢,合并插入緩沖业扒,刷新臟頁等。master thread大致分為每秒運行一次的操作和每10秒運行一次的操作舒萎。master thread中刷新數(shù)據(jù)程储,屬于checkpoint的一種。所以如果在master thread在刷新日志的間隙,DB出現(xiàn)故障那么將丟失掉這部分數(shù)據(jù)章鲤。
當(dāng)該值為2時摊灭,當(dāng)DB發(fā)生故障能恢復(fù)數(shù)據(jù)。但如果操作系統(tǒng)也出現(xiàn)宕機败徊,那么就會丟失掉帚呼,文件系統(tǒng)沒有及時寫入磁盤的數(shù)據(jù)。
這里說明一下皱蹦,innodb_flush_log_at_trx_commit
設(shè)為非0的值煤杀,并不是說不會在master thread中刷新日志了。master thread刷新日志是在不斷進行的沪哺,所以redo log寫入磁盤是在持續(xù)的寫入沈自。
五、 宕機恢復(fù)
DB宕機后重啟凤粗,InnoDB會首先去查看數(shù)據(jù)頁中的LSN的數(shù)值酥泛。這個值代表數(shù)據(jù)頁被刷新回磁盤的LSN的大小。然后再去查看redo log的LSN的大小嫌拣。如果數(shù)據(jù)頁中的LSN值大說明數(shù)據(jù)頁領(lǐng)先于redo log刷新回磁盤柔袁,不需要進行恢復(fù)。反之需要從redo log中恢復(fù)數(shù)據(jù)异逐。
redo log的結(jié)構(gòu)
其實這一部分內(nèi)容日常工作中很少涉及到捶索,稍微了解一下就足夠了。
一灰瞻、 log block
Redo log的存儲都是以 塊(block) 為單位進行存儲的腥例,每個塊的大小為512字節(jié)。同磁盤扇區(qū)大小一致酝润,可以保證塊的寫入是原子操作燎竖。
塊由三部分所構(gòu)成,分別是 日志塊頭(log block header)要销,日志塊尾(log block tailer)构回,日志本身。
日志頭占用12字節(jié)疏咐,日志尾占用8字節(jié)纤掸。故每個塊實際存儲日志的大小為492字節(jié)。
二浑塞、 log group
一個日志文件由多個塊所構(gòu)成借跪,多個日志文件形成一個重做日志文件組(redo log group)。不過酌壕,log group是一個邏輯上的概念掏愁,真實的磁盤上不會這樣存儲歇由。