數(shù)據(jù)庫(kù)日志——binlog、redo log、undo log掃盲
發(fā)布日期:2023/1/4 13:56:52 瀏覽量:
轉(zhuǎn)自博客園 作者: DiligentCoder原文鏈接:https://www.cnblogs.com/LoveShare/p/17024513.html
如有侵權(quán)請(qǐng)聯(lián)系我們立即刪除!
日志是數(shù)據(jù)庫(kù)中比較重要的組成部分,很多核心的功能必須依靠日志才能完成。
該篇文章簡(jiǎn)要介紹了binlog、redo log與undo log,能夠在一定程度上拓寬對(duì)mysql日志的整體認(rèn)識(shí)。
binlog
又稱歸檔日志,由Server層實(shí)現(xiàn)與記錄,因此對(duì)任何引擎都有效。
binlog是一種只記錄對(duì)表中數(shù)據(jù)以及對(duì)表結(jié)構(gòu)產(chǎn)生更改操作的二進(jìn)制文件,比如有insert、update、delete、create table、alter table等操作,不記錄select、show,因?yàn)檫@些操作不會(huì)產(chǎn)生任何更改。不過就算一個(gè)update未產(chǎn)生數(shù)據(jù)變化,也是會(huì)被記錄進(jìn)去的。
你可以理解binlog是直接記錄sql語(yǔ)句,或者說記錄原始sql邏輯,因此binlog屬于邏輯日志。
binlog是追加寫入的,一個(gè)文件寫滿,會(huì)重新創(chuàng)建一個(gè)文件繼續(xù)寫,文件名稱是mysql-bin.xxxxxx,例如myql-bin.000001,序號(hào)部分會(huì)遞增。
binlog的格式
binlog有三種格式,可以通過binlog-format來設(shè)定
STATEMENT
直接記錄操作的sql語(yǔ)句,例如update student set name=’tom’ where id=1;
優(yōu)點(diǎn):
這種格式的binlog,可以直接進(jìn)行閱讀。
不記錄具體的行數(shù)據(jù),日志量不會(huì)很大,性能較優(yōu)。
缺點(diǎn):
當(dāng)binlog用于主從之間的復(fù)制時(shí),如果當(dāng)前的sql語(yǔ)句為隨機(jī)函數(shù)rand()、當(dāng)前日期now()等,在重現(xiàn)之后具有不同的值,具有歧義性,可能會(huì)造成復(fù)制后數(shù)據(jù)不一致。
ROW
對(duì)于update student set name=’tom’ where id=1操作,會(huì)記錄id=1這條數(shù)據(jù)中name字段在修改前與修改后的數(shù)據(jù)。
優(yōu)點(diǎn):
準(zhǔn)確性強(qiáng)
缺點(diǎn):
可讀性差,需要借助mysqlbinlog解析。
如果經(jīng)常修改一些字段比較長(zhǎng)的數(shù)據(jù),會(huì)造成生成的binlog日志量變多,性能稍弱。
當(dāng)然,alter table等直接改變表結(jié)構(gòu)的語(yǔ)句,也會(huì)快速增加日志量與磁盤IO。
MIXED
其實(shí)就是一種對(duì)STATEMENT與ROW的混合使用方式
對(duì)不會(huì)造成歧義的操作使用STATEMENT格式進(jìn)行記錄,否則使用ROW格式記錄。
對(duì)表結(jié)構(gòu)的修改操作,也使用ROW格式進(jìn)行記錄。
不過,比較推薦的是ROW格式,特別是在SSD、云端存儲(chǔ)、大帶寬普及的今天,這點(diǎn)兒的存儲(chǔ)空間與磁盤IO還是吃得消的,滴滴基于Binlog的采集架構(gòu)就是直接使用的ROW格式。
binlog的使用場(chǎng)景
主從復(fù)制
當(dāng)我們使用主從結(jié)構(gòu)的mysql時(shí),從庫(kù)需要同步主庫(kù)的數(shù)據(jù)。
這個(gè)時(shí)候主庫(kù)會(huì)將自己的binlog異步發(fā)送給從庫(kù),從庫(kù)在本地完成sql回放,來達(dá)到主從數(shù)據(jù)一致的目的。
主從復(fù)制之間可能會(huì)存在延遲,當(dāng)主庫(kù)只負(fù)責(zé)寫,從庫(kù)只負(fù)責(zé)讀時(shí),寫完主庫(kù)之后的立馬讀從庫(kù),可能會(huì)出現(xiàn)問題。
關(guān)于主從復(fù)制原理及主從延遲的解決方案,會(huì)另開篇幅。
數(shù)據(jù)恢復(fù)
當(dāng)誤刪生產(chǎn)數(shù)據(jù)時(shí),可以通過binlog來恢復(fù)。
找到生產(chǎn)庫(kù)最近的一次全量備份,首先由全量備份恢復(fù)到臨時(shí)庫(kù)中。
接著從全量備份的時(shí)間點(diǎn)開始,重放binlog一直到mysql不產(chǎn)生新的binlog為止,另外要注意刪除binlog中誤操作的語(yǔ)句,最后切換臨時(shí)庫(kù)為生產(chǎn)庫(kù)。
值得注意的一點(diǎn)是,binlog默認(rèn)是不開啟的。
redo log
又稱重做日志,是Innodb引擎中特有的日志。如果當(dāng)前使用的引擎是Myisam或者M(jìn)emory,那就無從談起redo log。
和binlog的內(nèi)容不同,redo log記錄了“在某個(gè)數(shù)據(jù)頁(yè)上做了哪些修改”,屬于物理日志。
為什么要有redo log?
Innodb引擎是以頁(yè)為單位來和磁盤交互的,一般來說,如果一個(gè)事務(wù)提交后,需要將修改后的數(shù)據(jù)頁(yè)寫回到磁盤中。
如果本次事務(wù)只修改當(dāng)前數(shù)據(jù)頁(yè)中的幾個(gè)Byte,直接將當(dāng)前數(shù)據(jù)頁(yè)的所有內(nèi)容刷到磁盤后,涉及到大量的隨機(jī)寫,IO成本很高,性能比較低。
如果事務(wù)提交后,先將“對(duì)哪個(gè)數(shù)據(jù)頁(yè)做了哪些修改”順序?qū)?/strong>入redo log,之后會(huì)在合適的時(shí)機(jī)寫回到buffer pool(你可以把buffer pool理解為緩沖池,如果查詢到一條記錄時(shí),會(huì)將記錄所在的數(shù)據(jù)頁(yè)加載進(jìn)緩沖池中。之后再進(jìn)行查找時(shí),先查詢緩沖池,查不到再查磁盤,查到了就再放入到緩沖池中。這樣做,在一定程度上可以減少IO成本,提升性能)中,最后將buffer pool中的數(shù)據(jù)頁(yè)刷盤,在一定程度上可以減少IO成本。
此外,binlog是不支持crash-safe,即崩潰恢復(fù)的,只是支持誤刪數(shù)據(jù)恢復(fù)。當(dāng)redo log與binlog結(jié)合在一起的時(shí)候,光芒就出現(xiàn)了,此處應(yīng)該有迪迦。redo log中較實(shí)際數(shù)據(jù)頁(yè)中多出來的那部分日志,就是崩潰后用于恢復(fù)的日志。
redo log的記錄方式
和binlog追加寫不同,redo log采用的是循環(huán)寫。之所以用循環(huán)寫,是因?yàn)橹盎謴?fù)的數(shù)據(jù)再保存在redo log中就沒有任何意義了。
假設(shè)redo log最終會(huì)寫入到4個(gè)文件中,每個(gè)文件的大小都是1GB,則此時(shí)能夠記錄的最大日志量為4GB。
比如先從1號(hào)文件中寫入,寫滿之后,就換到2號(hào)文件中。4個(gè)文件全部寫滿后,再回到1號(hào)文件從頭繼續(xù)寫。
這里還有兩個(gè)指針,write position與check point
write position
指向redo log的記錄進(jìn)度,write position指針走過的區(qū)域,代表著redo log的日志量逐漸增長(zhǎng)。
check point
指向數(shù)據(jù)頁(yè)刷盤后的恢復(fù)進(jìn)度,check point指針走過的區(qū)域,會(huì)將區(qū)域內(nèi)redo log數(shù)據(jù)用于恢復(fù),接著將redo log擦除。
兩個(gè)指針的運(yùn)動(dòng)方向,都是順時(shí)針方向。
因此,從write position順時(shí)針到check point之間的區(qū)域,都是空著的部分。
當(dāng)redo log記錄過快時(shí),write position可能會(huì)追趕上check point。此時(shí)就需要停止redo log記錄,并將所有文件中的redo log恢復(fù)。
在這里,有必要總結(jié)一下binlog與redo log的區(qū)別。
binlog與redo log的區(qū)別
| binlog | redo log | |
|---|---|---|
| 日志歸屬 | 由Server層實(shí)現(xiàn),所有的引擎都可以使用 | Innodb引擎中特有的日志 |
| 日志類型 | 邏輯日志,記錄原始的sql邏輯或數(shù)據(jù)變更的前后內(nèi)容 | 物理日志,記錄在哪個(gè)數(shù)據(jù)頁(yè)上進(jìn)行了哪些更改 |
| 寫入方式 | 追加寫,寫滿則創(chuàng)建一個(gè)新文件繼續(xù)寫 | 循環(huán)寫,全部寫滿就從頭開始 |
| 適用場(chǎng)景 | 主從同步與誤刪恢復(fù) | 崩潰恢復(fù) |
在一條類型為update的sql語(yǔ)句的執(zhí)行背后,涉及到binglog與redo log的兩階段提交,這個(gè)也會(huì)另開篇幅。
Undo log
undo log主要用于事務(wù)回滾時(shí)恢復(fù)原來的數(shù)據(jù)
mysql在執(zhí)行sql語(yǔ)句時(shí),會(huì)將一條邏輯相反的日志保存到undo log中。因此,undo log中記錄的也是邏輯日志。
當(dāng)sql語(yǔ)句為insert時(shí),會(huì)在undo log中記錄本次插入的主鍵id。等事務(wù)回滾時(shí),delete此id即可。
當(dāng)sql語(yǔ)句為update時(shí),會(huì)在undo log中記錄修改前的數(shù)據(jù)。等事務(wù)回滾時(shí),再執(zhí)行一次update,得到原來的數(shù)據(jù)。
當(dāng)sql語(yǔ)句為delete時(shí),會(huì)在undo log中記錄刪除前的數(shù)據(jù)。等事務(wù)回滾時(shí),insert原來的數(shù)據(jù)即可。
數(shù)據(jù)庫(kù)事務(wù)四大特性中的原子性,即事務(wù)具有不可分割性,要么全部成功,要么全部失敗,其底層就靠undo log實(shí)現(xiàn)。在某一步執(zhí)行失敗時(shí),會(huì)對(duì)之前事務(wù)的語(yǔ)句進(jìn)行回滾。
另外,undo log與ReadView合作可以實(shí)現(xiàn)多版本并發(fā)控制MVCC(Mutil-Version Concurrency Control)。
MVCC
對(duì)于MVCC,簡(jiǎn)單來講,就是mysql保存了一行數(shù)據(jù)在多個(gè)時(shí)間點(diǎn)的快照,是一種使用空間換取時(shí)間的策略,能做到讀(快照讀,可以理解就是普通的select語(yǔ)句)寫不加鎖。
你可以暫時(shí)理解為,每一份快照包含了一行undo log日志,各個(gè)版本的快照通過指針連接起來,這樣可以順著指針快速找到上一份快照。
(圖片來源于互聯(lián)網(wǎng),聯(lián)系侵刪)
馬上咨詢: 如果您有業(yè)務(wù)方面的問題或者需求,歡迎您咨詢!我們帶來的不僅僅是技術(shù),還有行業(yè)經(jīng)驗(yàn)積累。
QQ: 39764417/308460098 Phone: 13 9800 1 9844 / 135 6887 9550 聯(lián)系人:石先生/雷先生