MySQL中的三大日志用法及分析
MySQL中三大日志用法
- undolog日志是inndb存儲(chǔ)引擎層生成的日志,實(shí)現(xiàn)了事務(wù)的原子性,主要用于事務(wù)回滾和MVCC。
- redolog日志是inndb存儲(chǔ)引擎層生成的日志,實(shí)現(xiàn)了事務(wù)的持久性,主要用于掉電等故障恢復(fù)。
- binlog日志是Server層生成的日志,主要用于數(shù)據(jù)備份和主從復(fù)制。
undolog回滾日志
undolog是如何實(shí)現(xiàn)事務(wù)回滾和MVCC?
三個(gè)隱藏字段:事務(wù)id、回滾指針、主鍵(如果我們?cè)诒碇袥]有指定主鍵,則會(huì)創(chuàng)建一個(gè)默認(rèn)的隱藏主鍵row_id,如果表中有主鍵,則不會(huì)創(chuàng)建)。
在我們開啟事務(wù)后,執(zhí)行事務(wù)的過程中,如果我們對(duì)數(shù)據(jù)進(jìn)行增刪改操作,會(huì)先記錄undolog日志,記錄數(shù)據(jù)變更之前的信息,然后更新數(shù)據(jù)庫中的記錄,并且記錄本次操作的事務(wù)ID、回滾指針。通過回滾指針,我們可以構(gòu)建出每條記錄的版本鏈,即數(shù)據(jù)庫中每一條記錄的歷史版本信息。
通過構(gòu)建的版本鏈,如果我們?cè)趫?zhí)行事務(wù)的過程中發(fā)生了異常,這時(shí)候就會(huì)根據(jù)版本鏈的信息將每條記錄中回滾到舊值。

MVCC的實(shí)現(xiàn)是利用版本鏈和開啟ReadView快照讀時(shí)記錄的信息,根據(jù)一定的規(guī)則去判斷修改記錄的事務(wù)是否已經(jīng)提交。如果提交了,在讀已提交的隔離級(jí)別下就可以讀取到已提交事務(wù)的信息了;如果在可重復(fù)讀隔離級(jí)別下,則會(huì)在后續(xù)的ReadView中復(fù)用之前的視圖,只能看到第一次創(chuàng)建ReadView時(shí)候的數(shù)據(jù)信息。
redolog重做日志
為什么需要redolog,解決了什么問題?
我們做數(shù)據(jù)的增刪改操作時(shí),并不是直接將數(shù)據(jù)寫入到磁盤中,而是先將數(shù)據(jù)寫入到Buffer Pool緩存中。如果我們每次將數(shù)據(jù)都寫入到磁盤,將會(huì)導(dǎo)致磁盤I/O頻繁,內(nèi)存開銷大。
有了Buffer Pool之后,我們的具體操作流程為:
- 讀取數(shù)據(jù)時(shí),如果數(shù)據(jù)存在于Buffer Pool中,客戶端直接讀取Buffer Pool中的數(shù)據(jù),否則再去磁盤中讀取。
- 當(dāng)修改數(shù)據(jù)時(shí),如果數(shù)據(jù)存在于Buffer Pool當(dāng)中,那直接修改Buffer Pool所在的頁,然后將其頁設(shè)置為臟頁(該頁內(nèi)存數(shù)據(jù)和磁盤數(shù)據(jù)已經(jīng)不一致了),為了減少磁盤I/O,不會(huì)立即將臟頁寫入到磁盤,后續(xù)由后臺(tái)線程在一個(gè)合適的時(shí)機(jī)將臟頁寫入磁盤。
引入Buffer Pool做數(shù)據(jù)緩存解決了頻繁讀寫I/O的問題,但是又導(dǎo)致了緩存中的數(shù)據(jù)和磁盤中的數(shù)據(jù)存在不一致的問題。即我們更新完緩存中的數(shù)據(jù),這時(shí)候還沒來得及更新磁盤中的數(shù)據(jù),mysql發(fā)生故障,導(dǎo)致緩存中的數(shù)據(jù)丟失,數(shù)據(jù)持久化失敗。
為了解決這個(gè)問題,MySQL在Innodb存儲(chǔ)引擎層引入了redolog日志。這時(shí)候,當(dāng)有一條數(shù)據(jù)更新的時(shí)候,InnoDB引擎就會(huì)先更新內(nèi)存(同時(shí)標(biāo)記為臟頁),然后將本次對(duì)這個(gè)頁的修改以redo log的形式記錄下來,這時(shí)候更新就算完成了。后續(xù)InnoDB存儲(chǔ)引擎會(huì)在后臺(tái)啟動(dòng)一個(gè)線程,將redolog中的記錄寫入到磁盤中,并將binlog中已經(jīng)寫入磁盤的內(nèi)容清空,這時(shí)候更新操作最終完成。
有的同學(xué)可能會(huì)有疑問?我將更新的操作寫入到redolog中也是做磁盤的IO操作,為什么不直接將數(shù)據(jù)寫入到數(shù)據(jù)庫中呢?先寫入到redolog中,再寫入到數(shù)據(jù)庫中不是更加浪費(fèi)開銷嗎?
要解答這個(gè)問題,首先我們需要先了解一下常見的兩種寫入磁盤的方式:
- 順序?qū)懭?/strong>:我們向磁盤中寫入數(shù)據(jù)遵循一定的規(guī)則,比如從頭到尾。
- 隨機(jī)寫入:我們向磁盤中寫入數(shù)據(jù)是隨機(jī)的,一會(huì)寫到這里,一會(huì)寫到那里。
打個(gè)比方:就像我們寫作業(yè)一樣,順序?qū)懭胧菑牡谝豁搶懙阶詈笠豁?;而隨機(jī)寫入則是我們一會(huì)寫到第一頁,一會(huì)寫到第五頁。我們進(jìn)行順序?qū)懭胧遣僮鞅入S機(jī)寫入的操作要快很多,這也是MySQL為什么引入redolog的另一個(gè)目的。
redolog的兩大作用:
- 將臟頁數(shù)據(jù)保存下來,實(shí)現(xiàn)事務(wù)的持久化。
- 提高讀寫效率,將MySQL的隨機(jī)寫入轉(zhuǎn)變?yōu)轫樞驅(qū)懭搿?/li>
什么時(shí)候持久化:
- 后臺(tái)的進(jìn)程會(huì)每隔一秒將redolog中的日志寫入到磁盤中。
- 即使目前事務(wù)還沒有提交,如果沒有提交,會(huì)在mysql異常重啟之后進(jìn)行回滾操作。
binlog記錄日志
我們前面介紹的undolog和redolog都是InnDB存儲(chǔ)引擎層生成的日志。
MySQL在完成一條更新操作后,Server層還會(huì)生成一條binlog,等之后事務(wù)提交的時(shí)候,會(huì)將該事務(wù)執(zhí)行過程中產(chǎn)生的所有binlog統(tǒng)一寫入binlog文件。
binlog文件記錄了所有的數(shù)據(jù)庫表結(jié)構(gòu)變更和表數(shù)據(jù)修改的日志,不會(huì)記錄查詢類的操作,比如SELECT、SHOW操作。
為什么要有binlog日志,binlog和redolog的區(qū)別是什么?
我們先來談一談為什么要有binlog日志?
如果我們的數(shù)據(jù)庫是因?yàn)榇疟P故障或者損壞引起的,這時(shí)候可能發(fā)生數(shù)據(jù)丟失。在這種情況下,數(shù)據(jù)庫可能無法正常啟動(dòng)或者無法讀取先前持久化的數(shù)據(jù)。如果數(shù)據(jù)庫中存儲(chǔ)了重要的數(shù)據(jù),必須進(jìn)行恢復(fù),這時(shí)候通過undolog和redolog都是沒有辦法恢復(fù)的。undolog記錄的是當(dāng)前事務(wù)的執(zhí)行語句的相反操作,只能用于事務(wù)的回滾。redolog僅僅記錄的是內(nèi)存中已經(jīng)更改的數(shù)據(jù)但是磁盤上未進(jìn)行更改的數(shù)據(jù),隨著redolog刷盤條件的達(dá)成,redolog中的記錄會(huì)刪除,也就是說,通過redolog只能夠恢復(fù)部分?jǐn)?shù)據(jù),僅為redolog記錄的僅僅是一定范圍內(nèi)的數(shù)據(jù),有限。
這時(shí)候,我們就想,如果能夠一個(gè)日志系統(tǒng),能夠?qū)?shù)據(jù)庫的所有DML語句都記錄下來,并且不斷地堆積,那該多好啊!這就是MySQL中binlog的作用,用于做數(shù)據(jù)備份和數(shù)據(jù)的恢復(fù)。
除了數(shù)據(jù)備份和恢復(fù)外,binlog還用于實(shí)現(xiàn)主從復(fù)制。因?yàn)閎inlog中記錄的所有DML語句,如果想要在另一個(gè)服務(wù)器上復(fù)制這一個(gè)表,只需要將binlog文件在想要復(fù)制的服務(wù)器上重新執(zhí)行一遍即可。
binlog只有在事務(wù)提交的時(shí)候,才會(huì)將binlog日志持久化到本地。
總結(jié)
MySQL當(dāng)中的三大日志,作用不同,互為補(bǔ)充,提高了數(shù)據(jù)存儲(chǔ)的安全性和一致性。
其中,undolog和redolog用于實(shí)現(xiàn)InnoDB存儲(chǔ)引擎中事務(wù)四大特性的原子性和持久性,保證小范圍內(nèi)的數(shù)據(jù)一致性。binlog用于實(shí)現(xiàn)數(shù)據(jù)庫的全量備份,為數(shù)據(jù)恢復(fù)提供了一種重要的方式,值得注意的是,如果我們想要通過binlog恢復(fù)數(shù)據(jù)庫中的所有信息,就需要定期的進(jìn)行數(shù)據(jù)備份。因?yàn)?mysql僅會(huì)保證一定數(shù)量的數(shù)據(jù)文件,如果超過了該數(shù)量會(huì)將舊值刪除。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Ubuntu系統(tǒng)安裝mysql超詳細(xì)步驟
這篇文章主要給大家介紹了關(guān)于Ubuntu系統(tǒng)安裝mysql的相關(guān)資料,現(xiàn)在的軟件越來越好安裝,尤其是在ubuntu下安裝軟件,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09
mysql數(shù)據(jù)庫重置表主鍵id的實(shí)現(xiàn)
在我們的開發(fā)過程中,難免在做測(cè)試的時(shí)候會(huì)生成一些雜亂無章的SQL主鍵數(shù)據(jù),本文主要介紹了mysql數(shù)據(jù)庫重置表主鍵id的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2025-03-03
MySQL執(zhí)行SQL文件的常見場(chǎng)景與方法
MySQL?作為世界上最流行的開源關(guān)系型數(shù)據(jù)庫管理系統(tǒng),在日常開發(fā)和運(yùn)維工作中扮演著重要角色,本文主要介紹了MySQL?執(zhí)行?SQL?文件的主要方法與場(chǎng)景,希望對(duì)大家有所幫助2025-06-06
mysql_connect(): Connection using old (pre-4.1.1) authentica
MySQL錯(cuò)誤提示:Connection using old (pre-4.1.1) authentication protocol refused (client option ‘secure_auth’ enabled)解決辦法,需要的朋友可以參考下2014-04-04

