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、回滾指針、主鍵(如果我們在表中沒有指定主鍵,則會(huì)創(chuàng)建一個(gè)默認(rèn)的隱藏主鍵row_id,如果表中有主鍵,則不會(huì)創(chuàng)建)。
在我們開啟事務(wù)后,執(zhí)行事務(wù)的過程中,如果我們對數(shù)據(jù)進(jìn)行增刪改操作,會(huì)先記錄undolog日志,記錄數(shù)據(jù)變更之前的信息,然后更新數(shù)據(jù)庫中的記錄,并且記錄本次操作的事務(wù)ID、回滾指針。通過回滾指針,我們可以構(gòu)建出每條記錄的版本鏈,即數(shù)據(jù)庫中每一條記錄的歷史版本信息。
通過構(gòu)建的版本鏈,如果我們在執(zhí)行事務(wù)的過程中發(fā)生了異常,這時(shí)候就會(huì)根據(jù)版本鏈的信息將每條記錄中回滾到舊值。
MVCC的實(shí)現(xiàn)是利用版本鏈和開啟ReadView快照讀時(shí)記錄的信息,根據(jù)一定的規(guī)則去判斷修改記錄的事務(wù)是否已經(jīng)提交。如果提交了,在讀已提交的隔離級別下就可以讀取到已提交事務(wù)的信息了;如果在可重復(fù)讀隔離級別下,則會(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ù)由后臺線程在一個(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)記為臟頁),然后將本次對這個(gè)頁的修改以redo log的形式記錄下來,這時(shí)候更新就算完成了。后續(xù)InnoDB存儲(chǔ)引擎會(huì)在后臺啟動(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ū)懭胧菑牡谝豁搶懙阶詈笠豁摚欢S機(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í)候持久化:
- 后臺的進(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)文章
淺談Mysql連接數(shù)據(jù)庫時(shí)host和user的匹配規(guī)則
這篇文章主要介紹了淺談Mysql連接數(shù)據(jù)庫時(shí)host和user的匹配規(guī)則,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01mysql數(shù)據(jù)庫日志binlog保存時(shí)效問題(expire_logs_days)
這篇文章主要介紹了mysql數(shù)據(jù)庫日志binlog保存時(shí)效問題(expire_logs_days),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03在IDEA的maven項(xiàng)目中連接并使用MySQL8.0的方法教程
這篇文章主要介紹了如何在IDEA的maven項(xiàng)目中連接并使用MySQL8.0,本文分步驟給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02通過實(shí)例分析MySQL中的四種事務(wù)隔離級別
SQL標(biāo)準(zhǔn)定義了4種隔離級別,包括了一些具體規(guī)則,用來限定事務(wù)內(nèi)外的哪些改變是可見的,哪些是不可見的。下面這篇文章通過實(shí)例詳細(xì)的給大家分析了關(guān)于MySQL中的四種事務(wù)隔離級別的相關(guān)資料,需要的朋友可以參考下。2017-08-08MYSQL突破secure_file_priv寫shell問題
這篇文章主要介紹了MYSQL突破secure_file_priv寫shell問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01