必須了解的MySQL三種日志
文章已收錄Github精選,歡迎Star:https://github.com/yehongzhi/learningSummary
前言
大家有沒有想過為什么MySQL數(shù)據(jù)庫可以實現(xiàn)主從復制,實現(xiàn)持久化,實現(xiàn)回滾的呢?其實關鍵在于MySQL里的三種log,分別是:
binlog redo log undo log
這三種log也是面試經(jīng)常會問的問題,下面我們一起來探討一下吧。
一、binlog
binlog應該是日常中聽的最多的關于mysql中的log。
那么什么是binlog呢?
binlog是用于記錄數(shù)據(jù)庫表結構和表數(shù)據(jù)變更的二進制日志,比如insert、update、delete、create、truncate等等操作,不會記錄select、show操作,因為沒有對數(shù)據(jù)本身發(fā)生變更。
binlog文件長什么樣子呢?
使用mysqlbinlog命令可以查看。

會記錄下每條變更的sql語句,還有執(zhí)行開始時間,結束時間,事務id等等信息。
如何查看binlog是否打開,如果沒打開怎么設置?
使用命令show variables like '%log_bin%';查看binlog是否打開。

如果像上圖一樣,沒有開啟binlog,那怎么開啟呢?
找到my.cnf配置文件,增加下面配置(mysql版本5.7.31):
# 打開binlog
log-bin=mysql-bin
# 選擇ROW(行)模式
binlog-format=ROW
修改后,重啟mysql,配置生效。
執(zhí)行SHOW MASTER STATUS;可以查看當前寫入的binlog文件名。

binlog用來干嘛的呢?
第一,用于主從復制。一般在公司中做一主二從的結構時,就需要master節(jié)點打開binlog日志,從機訂閱binlog日志的信息,因為binlog日志記錄了數(shù)據(jù)庫數(shù)據(jù)的變更,所以當master發(fā)生數(shù)據(jù)變更時,從機也能隨著master節(jié)點的數(shù)據(jù)變更而變更,做到主從復制的效果。

第二,用于數(shù)據(jù)恢復。因為binlog記錄了數(shù)據(jù)庫的變更,所以可以用于數(shù)據(jù)恢復。我們看到上面圖中有個字段叫Position,這個參數(shù)是用于記錄binlog日志的指針。當我們需要恢復數(shù)據(jù)時,只要指定--start-position和--stop-position,或者指定--start-datetime和--stop-datetime,那么就可以恢復指定區(qū)間的數(shù)據(jù)。
二、redo log
假設有一條update語句:
UPDATE `user` SET `name`='劉德華' WHERE `id`='1';
我們想象一下mysql修改數(shù)據(jù)的步驟,肯定是先把id='1'的數(shù)據(jù)查出來,然后修改名稱為'劉德華'。再深層一點,mysql是使用頁作為存儲結構,所以MySQL會先把這條記錄所在的頁加載到內(nèi)存中,然后對記錄進行修改。但是我們都知道m(xù)ysql支持持久化,最終數(shù)據(jù)都是存在于磁盤中。
假設需要修改的數(shù)據(jù)加載到內(nèi)存中,并且修改成功了,但是還沒來得及刷到磁盤中,這時數(shù)據(jù)庫宕機了,那么這次修改成功后的數(shù)據(jù)就丟失了。
為了避免出現(xiàn)這種問題,MySQL引入了redo log。

如圖所示,當執(zhí)行數(shù)據(jù)變更操作時,首先把數(shù)據(jù)也加載到內(nèi)存中,然后在內(nèi)存中進行更新,更新完成后寫入到redo log buffer中,然后由redo log buffer在寫入到redo log file中。
redo log file記錄著xxx頁做了xxx修改,所以即使mysql發(fā)生宕機,也可以通過redo log進行數(shù)據(jù)恢復,也就是說在內(nèi)存中更新成功后,即使沒有刷新到磁盤中,但也不會因為宕機而導致數(shù)據(jù)丟失。
redo log與事務機制是如何配合工作的?

如圖所示:
第1-3步驟就是把數(shù)據(jù)變更,然后寫入到內(nèi)存中。
第4步記錄到redo log中,然后把記錄置為prepare(準備)狀態(tài)。
第5,6步提交事務,提交事務之后,第7步把記錄狀態(tài)改成commit(提交)狀態(tài)。
保證了事務與redo log的一致性。
binlog和redo log都可以數(shù)據(jù)恢復,有什么區(qū)別?
redo log是恢復在內(nèi)存更新后,還沒來得及刷到磁盤的數(shù)據(jù)。
binlog是存儲所有數(shù)據(jù)變更的情況,理論上只要記錄在binlog上的數(shù)據(jù),都可以恢復。
舉個例子,假如不小心整個數(shù)據(jù)庫的數(shù)據(jù)被刪除了,能使用redo log文件恢復數(shù)據(jù)嗎?
不可以使用redo log文件恢復,只能使用binlog文件恢復。因為redo log文件不會存儲歷史所有的數(shù)據(jù)的變更,當內(nèi)存數(shù)據(jù)刷新到磁盤中,redo log的數(shù)據(jù)就失效了,也就是redo log文件內(nèi)容是會被覆蓋的。
binlog又是在什么時候記錄的呢?
答,在提交事務的時候。

三、undo log
undo log的作用主要用于回滾,mysql數(shù)據(jù)庫的事務的原子性就是通過undo log實現(xiàn)的。我們都知道原子性是指對數(shù)據(jù)庫的一系列操作,要么全部成功,要么全部失敗。
undo log主要存儲的是數(shù)據(jù)的邏輯變化日志,比如說我們要insert一條數(shù)據(jù),那么undo log就會生成一條對應的delete日志。簡單點說,undo log記錄的是數(shù)據(jù)修改之前的數(shù)據(jù),因為需要支持回滾。
那么當需要回滾時,只需要利用undo log的日志就可以恢復到修改前的數(shù)據(jù)。
undo log另一個作用是實現(xiàn)多版本控制(MVCC),undo記錄中包含了記錄更改前的鏡像,如果更改數(shù)據(jù)的事務未提交,對于隔離級別大于等于read commit的事務而言,不應該返回更改后數(shù)據(jù),而應該返回老版本的數(shù)據(jù)。
總結
學完之后,我們知道這三種日志在mysql中都有著重要的作用,再回顧一下:
binlog主要用于復制和數(shù)據(jù)恢復。 redo log用于恢復在內(nèi)存更新后,還沒來得及刷到磁盤的數(shù)據(jù)。 undo log用于實現(xiàn)回滾和多版本控制。
這篇文章就講到這里了,感謝大家的閱讀,希望看完大家能有所收獲!
覺得有用就點個贊吧,你的點贊是我創(chuàng)作的最大動力~
我是一個努力讓大家記住的程序員。我們下期再見!!!
能力有限,如果有什么錯誤或者不當之處,請大家批評指正,一起學習交流!
