前言
MySQL 日志包含了錯(cuò)誤日志摊沉、查詢(xún)?nèi)罩境Р啤⒙樵?xún)?nèi)罩居蟛尽⑹聞?wù)日志、二進(jìn)制日志等璃饱,如果存儲(chǔ)引擎使用的是 InnoDB 与斤,二進(jìn)制日志(binlog)和事務(wù)日志(包括redo log和undo log) 是肯定繞不過(guò)去的,本篇接下來(lái)詳細(xì)為大家介紹這三種日志荚恶。
redo log
為什么要有 redo log 撩穿?
我們都清楚,事務(wù)的四大特性其中有一個(gè)是持久性裆甩,簡(jiǎn)單的說(shuō)就是只要事務(wù)提交成功冗锁,對(duì)數(shù)據(jù)庫(kù)做的修改就會(huì)被永久保存下來(lái),不會(huì)因?yàn)槿魏卧蛟倩氐皆瓉?lái)的狀態(tài)嗤栓。
MySQL 是怎么樣保證持久性的呢冻河?最簡(jiǎn)單的做法是在每次事務(wù)提交的時(shí)候,將該事務(wù)涉及修改的數(shù)據(jù)頁(yè)全部刷新回磁盤(pán)中茉帅,可是這么做存在嚴(yán)重的性能問(wèn)題:
單個(gè)事務(wù)可能涉及修改多個(gè)數(shù)據(jù)頁(yè)叨叙,并且數(shù)據(jù)頁(yè)在物理上并不連續(xù),使用隨機(jī)IO寫(xiě)入性能太差堪澎。
Innodb是以頁(yè)為單位進(jìn)行磁盤(pán)交互的擂错,一個(gè)事務(wù)有可能只會(huì)修改一個(gè)數(shù)據(jù)頁(yè)中的幾個(gè)字節(jié),如果這時(shí)候?qū)⑼暾臄?shù)據(jù)頁(yè)刷回磁盤(pán)的話(huà)樱蛤,很浪費(fèi)資源钮呀。
因此 MySQL 設(shè)計(jì)出了redo log,當(dāng)一條記錄更新的時(shí)候昨凡, InnoDB 引擎會(huì)先把記錄寫(xiě)到 redo log 里面去爽醋,同時(shí)更新內(nèi)存,這樣就算這條數(shù)據(jù)更新成功了便脊,完美地解決了性能問(wèn)題(文件更小并且是順序IO)蚂四。
注意此時(shí)數(shù)據(jù)并沒(méi)有更新到磁盤(pán)上,InnoDB 會(huì)在恰當(dāng)?shù)臅r(shí)候把這條記錄更新到磁盤(pán)上去。這種先寫(xiě)日志然后再將數(shù)據(jù)刷盤(pán)的機(jī)制遂赠,有個(gè)專(zhuān)有名詞——WAL(Write-ahead logging)久妆。
redo log 如何刷到磁盤(pán)的呢?
redo log包含兩部分:
內(nèi)存中的日志緩沖(redo log buffer)
磁盤(pán)上的日志文件(redo log file)
每執(zhí)行一條DML語(yǔ)句跷睦,數(shù)據(jù)庫(kù)先將記錄寫(xiě)入redo log buffer筷弦,然后后續(xù)某個(gè)時(shí)間點(diǎn)再一次性將多個(gè)操作記錄寫(xiě)到redo log file。MySQL 一共支持三種寫(xiě)入redo log file的時(shí)機(jī)送讲,通過(guò)參數(shù) innodb_flush_log_at_trx_commit 進(jìn)行配置奸笤,如下圖所示:
bin log
bin log 是 MySQL 的邏輯日志,由Server層進(jìn)行記錄哼鬓,用于記錄數(shù)據(jù)庫(kù)執(zhí)行的寫(xiě)入性操作(不包括查詢(xún))信息监右,以二進(jìn)制的形式保存在磁盤(pán)中。無(wú)論你使用的是任何的存儲(chǔ)引擎异希,mysql數(shù)據(jù)庫(kù)都會(huì)記錄binlog日志健盒。
與redo log日志一樣,binlog也有自己的刷盤(pán)策略称簿,通過(guò)sync_binlog參數(shù)控制:
0 :每次提交事務(wù)前將binlog寫(xiě)入os cache扣癣,由操作系統(tǒng)控制什么時(shí)候刷到磁盤(pán)
1 :采用同步寫(xiě)磁盤(pán)的方式來(lái)寫(xiě)binlog,不使用os cache來(lái)寫(xiě)binlog
N :當(dāng)每進(jìn)行n次事務(wù)提交之后憨降,調(diào)用一次fsync() os cache中的binlog強(qiáng)制刷到磁盤(pán)
bin log 和 redo log 都用于記錄的修改之后的值父虑,那么它們之間究竟有什么區(qū)別呢?
redo log 和 binlog 的區(qū)別
主要有以下三方面:
binlog 是 MySQL 的 Server 層實(shí)現(xiàn)的授药,所有的引擎都是可以的士嚎。redo log是InnoDB的日志。如果不使用InnoDB引擎悔叽,是沒(méi)有redo log的莱衩。
binlog是邏輯日志,記錄的是對(duì)哪一個(gè)表的哪一行做了什么修改娇澎;redo log是物理日志笨蚁,記錄的是對(duì)哪個(gè)數(shù)據(jù)頁(yè)中的哪個(gè)記錄做了什么修改,可以理解為對(duì)磁盤(pán)上的哪個(gè)數(shù)據(jù)做了修改趟庄。
redo log 是有固定大小的括细,所以它的空間會(huì)用完,如果用完的話(huà)戚啥,一定要進(jìn)行一些寫(xiě)入磁盤(pán)的操作才可以繼續(xù); binlog 是可以追加寫(xiě)入的勒极,也就是 binlog 沒(méi)有空間的概念,一直寫(xiě)就行了
undo log
數(shù)據(jù)庫(kù)事務(wù)四大特性中有一個(gè)是原子性虑鼎,原子性指對(duì)數(shù)據(jù)庫(kù)的一系列操作,要么全部成功,要么全部失敗炫彩,不可能出現(xiàn)部分成功的情況匾七。實(shí)際上,原子性底層就是通過(guò)undo log實(shí)現(xiàn)的江兢。
undo log主要記錄了數(shù)據(jù)的邏輯變化昨忆,比如一條UPDATE語(yǔ)句,對(duì)應(yīng)一條相反UPDATE的undo log杉允,一條INSERT語(yǔ)句邑贴,對(duì)應(yīng)一條DELETE的undo log,這樣在發(fā)生錯(cuò)誤時(shí)叔磷,就能回滾到事務(wù)之前的數(shù)據(jù)狀態(tài)拢驾。
undo log 同時(shí)也是MVCC(多版本并發(fā)控制)實(shí)現(xiàn)的關(guān)鍵,這部分公眾號(hào)之前有講過(guò)改基,不再贅述繁疤。
總結(jié)
redo log是InnoDB存儲(chǔ)引擎的一種日志,主要作用是崩潰恢復(fù)秕狰,刷盤(pán)策略參數(shù) innodb_flush_log_at_trx_commit 推薦設(shè)置成2稠腊。
binlog是MySQL Server層的一種日志,主要作用是歸檔鸣哀。
undo log是InnoDB存儲(chǔ)引擎的一種日志架忌,主要作用是回滾。