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