極客時間MySQL專欄總結(jié)
使用InnoDB引擎過程中,比較耳熟能詳?shù)娜N日志:
- undo log:用于回滾;
- redo log:崩潰恢復(fù);
- bin log:備份、主從同步。
WAL技術(shù):Write-Ahead Logging,先寫日志,再寫磁盤。
如果每一次更新操作都要寫入磁盤,查找+寫入的IO成本很高,使用WAL技術(shù)可以避免。
redo log 重做日志
- InnoDB 引擎就會先把記錄寫到 redo log里面,并更新內(nèi)存,這個時候更新就算完成了;
-
同時,InnoDB 引擎會在適當(dāng)?shù)臅r候,將這個操作記錄更新到磁盤里面,而這個更新往往是在系統(tǒng)比較空閑的時候做。
redo log的大小是固定的,可以配置為一組四個的文件,每個文件的大小是1GB,那么總共就可以記錄4GB的操作。從頭開始寫,寫到末尾就回到開頭循環(huán)寫。
- write pos:當(dāng)前記錄的位置,一邊寫一遍后移,寫到3號文件末尾就回到0號文件開頭;
- check point:當(dāng)前要擦除的位置,也是往后推移并且循環(huán)的,擦除記錄前要把記錄更新到數(shù)據(jù)文件;
- write pos和check point之間是空白位置,可以用來記錄新的操作。如果write pos追上了check point,這時不能再執(zhí)行更新操作,要先停下來擦除一些記錄,把check point 推進一下。
個人理解redo log其實是利用了磁盤的順序?qū)懱岣咝阅?;redo log保證了crash-safe,已提交的數(shù)據(jù)不會丟失。
binlog 歸檔日志
歸檔:同義詞為存檔,指將處理完并且具有保存價值的事情或文件經(jīng)系統(tǒng)整理后交檔案室(館)保存?zhèn)浒?備查)的過程。
與 redo log 的不同
- redo log是InnoDB引擎特有的;bin log是MySQLServer層實現(xiàn)的,所有引擎都可以使用;
- redo log是物理日志,記錄的是“在某個數(shù)據(jù)頁上做了什么修改”;binlog是邏輯日志,記錄的是這個語句的原始邏輯;
- redo log是循環(huán)寫的,空間固定會被用完;binlog是可以追加寫入的。追加寫”是指 binlog 文件寫到一定大小后會切換到下一個,并不會覆蓋以前的日志。
為什么有兩份日志
最開始MySQL的設(shè)計是用binlog作為歸檔用途,且MySQL剛開始是沒有crash-safe能力的。后面出現(xiàn)了InnoDB引擎,通過redo log實現(xiàn)了crash-safe。
三種格式
- statement;
binlog記錄的是SQL語句原文。
在從庫執(zhí)行同樣的SQL語句時,可能由于使用不同的索引,導(dǎo)致語句執(zhí)行的效果不同,造成主從不一致。 - row;
binlog記錄的是真實行的數(shù)據(jù)。
不會有主備不一致問題,但是占用空間可能比較大。 - mixed。
statement和row的混合。
最好使用row格式,盡管可能會比較占用內(nèi)存,但是比較利于恢復(fù)數(shù)據(jù)。恢復(fù)數(shù)據(jù)時,最好使用mysqlbinlog工具接續(xù)出來,然后把解析的結(jié)果發(fā)給MySQL執(zhí)行。
更新時兩種日志的寫入

- 執(zhí)行器先找引擎取 ID=2 這一行。ID 是主鍵,引擎直接用樹搜索找到這一行。如果 ID=2 這一行所在的數(shù)據(jù)頁本來就在內(nèi)存中,就直接返回給執(zhí)行器;否則,需要先從磁盤讀入內(nèi)存,然后再返回。
- 執(zhí)行器拿到引擎給的行數(shù)據(jù),把這個值加上 1,比如原來是 N,現(xiàn)在就是 N+1,得到新的一行數(shù)據(jù),再調(diào)用引擎接口寫入這行新數(shù)據(jù)。
- 引擎將這行新數(shù)據(jù)更新到內(nèi)存中,同時將這個更新操作記錄到 redo log 里面,此時 redo log 處于 prepare 狀態(tài)。然后告知執(zhí)行器執(zhí)行完成了,隨時可以提交事務(wù)。
- 執(zhí)行器生成這個操作的 binlog,并把 binlog 寫入磁盤。
- 執(zhí)行器調(diào)用引擎的提交事務(wù)接口,引擎把剛剛寫入的 redo log 改成提交(commit)狀態(tài),更新完成。
- 兩階段提交
是為了讓兩份日志之間邏輯一致。
先寫redo log,可能導(dǎo)致binlog少一條,恢復(fù)臨時庫時與原庫不同;
先寫bin log,redo log少一條,崩潰恢復(fù)后沒有這條數(shù)據(jù),同樣導(dǎo)致臨時庫時與原庫不同。
雙1配置
- innodb_flush_log_at_trx_commit
這個參數(shù)設(shè)置成 1 的時候,表示每次事務(wù)的 redo log 都直接持久化到磁盤。 - sync_binlog
這個參數(shù)設(shè)置成 1 的時候,表示每次事務(wù)的 binlog 都持久化到磁盤。
undo log
MySQL的MVCC是基于undo log實現(xiàn)的,每次需要查詢歷史版本的數(shù)據(jù),是通過undo log計算出來的。
