參考博客:https://qimok.cn/584.html
重做日志(redo log)纷铣、回滾日志(undo log)、二進(jìn)制日志(binlog)战转,redo log 是物理日志搜立,undo log 和 binlog 是邏輯日志,物理日志的恢復(fù)速度遠(yuǎn)快于邏輯日志槐秧,這時(shí)因?yàn)閞edo log利用了磁盤的順序讀寫啄踊,mysql使用redo log提升了整體的io性能
redo log
參考博文:https://www.cnblogs.com/hapjin/archive/2019/09/28/11521506.html
概念
redo log在mysql中默認(rèn)以ib_logfile0,ib_logfile1名稱存在,可以手工修改參數(shù),調(diào)節(jié)開啟幾組日志來(lái)服務(wù)于當(dāng)前mysql數(shù)據(jù)庫(kù),mysql采用順序刁标,循環(huán)寫方式颠通,每開啟一個(gè)事務(wù)時(shí),會(huì)把一些相關(guān)信息記錄事務(wù)日志中(記錄對(duì)數(shù)據(jù)文件數(shù)據(jù)修改的物理位置或叫做偏移量);這個(gè)系列文件個(gè)數(shù)由參數(shù)innodb_log_files_in_group控制膀懈,若設(shè)置為4顿锰,則命名為ib_logfile0~3。這些文件的寫入是順序启搂、循環(huán)寫的硼控,logfile0寫完從logfile1繼續(xù),logfile3寫完則logfile0繼續(xù)狐血。他們的作用是在系統(tǒng)崩潰重啟時(shí)淀歇,作事務(wù)重做;在系統(tǒng)正常時(shí)匈织,每次checkpoint時(shí)間點(diǎn)浪默,會(huì)將之前寫入事務(wù)應(yīng)用到數(shù)據(jù)文件中。innodb 事務(wù)日志包括 redo log 和 undo log缀匕,redo log是物理日志,undo log 是邏輯日志纳决,用來(lái)提供回滾操作,redo log保證事務(wù)的持久性乡小,undo log保證事務(wù)的原子性阔加,兩者可以統(tǒng)稱為事務(wù)日志。而binloh與redo log不同點(diǎn)是:redo log 是循環(huán)寫的满钟,空間固定會(huì)用完胜榔;binlog 是可以追加寫入的∨确“追加寫”是指binlog 文件寫到一定大小后會(huì)切換到下一個(gè)夭织,并不會(huì)覆蓋以前的日志。
生命周期:
事務(wù)開始之后就開始產(chǎn)生 redo log 日志了吠撮,在事務(wù)執(zhí)行的過程中尊惰,當(dāng)對(duì)應(yīng)事務(wù)的臟頁(yè)會(huì)被記錄到redo log中,當(dāng) redo log file 大小已經(jīng)達(dá)到某個(gè)域值快要"不可用"時(shí)(日志文件組輪流寫文件),觸發(fā) checkpoint弄屡,及時(shí)將緩沖池的臟頁(yè)刷新到磁盤题禀,并同時(shí)將redo log buffer刷新到磁盤,redo log 的使命就完成了膀捷,它所占用的空間也就可以被覆蓋了迈嘹。
存儲(chǔ)內(nèi)容:
redo log 包括兩部分:一是內(nèi)存中的日志緩沖(redo log buffer),默認(rèn)大小16MB担孔,可經(jīng)過參數(shù)innodb_log_buffer_size動(dòng)態(tài)的調(diào)整它的大小江锨,該部分日志是易失性的;二是磁盤上的重做日志文件(redo log file)糕篇,該部分日志是持久的啄育,redo log 存儲(chǔ)的是物理格式的日志,記錄的是物理數(shù)據(jù)頁(yè)面的修改信息拌消,即所有innodb表數(shù)據(jù)的變化挑豌,它是順序?qū)懭?redo log file 中的。
持久化:
當(dāng)事務(wù)要修改記錄時(shí)墩崩,生成的日志都得先保存起來(lái)氓英,但又不能在還沒 commit 的時(shí)候就直接寫到 redo log 文件里。所以鹦筹,redo log buffer 就是一塊內(nèi)存,用以緩存事務(wù)執(zhí)行過程中的數(shù)據(jù)铝阐,記錄的物事務(wù)過程產(chǎn)生的修改,redo log buffer中同一個(gè)事務(wù)可能多次記錄铐拐,最后一個(gè)提交的事務(wù)記錄會(huì)覆蓋所有未提交的事務(wù)記錄徘键。當(dāng)向MySQL寫數(shù)據(jù)時(shí),先寫日志緩沖的redo log遍蟋,然后根據(jù)"某種方式"持久化到磁盤變成redo log file吹害。如果發(fā)生宕機(jī),則讀取磁盤上的 redo log file 進(jìn)行數(shù)據(jù)的恢復(fù)虚青。從這個(gè)角度來(lái)說它呀,MySQL 事務(wù)的持久性是通過 redo log 來(lái)實(shí)現(xiàn)的。
- 問:redo log buffer中的數(shù)據(jù)丟失了怎么辦棒厘?畢竟沒有寫到磁盤上纵穿,MySQL重啟后100%沒辦法將其恢復(fù)出來(lái)。
- 答:由于在MySQL的設(shè)定中奢人,當(dāng)你要Commit事務(wù)時(shí)谓媒,redo log才會(huì)持久化進(jìn)磁盤,既然你沒有commit达传,碰巧MySQL又宕機(jī)了篙耗。那讓MySQL正常重啟就行了啊,反正你沒有commit宪赶,MySQL也也沒有必要幫你恢復(fù)什么宗弯。
這三種狀態(tài)分別是:
- 存在 redo log buffer 中引几,物理上是在 MySQL 進(jìn)程內(nèi)存中昧互,就是圖中的紅色部分;
- 寫到磁盤 (write)伟桅,但是沒有持久化(fsync)敞掘,物理上是在文件系統(tǒng)的 page cache 里
面,也就是圖中的黃色部分楣铁; - 持久化到磁盤玖雁,對(duì)應(yīng)的是 hard disk,也就是圖中的綠色部分盖腕。
innodb_flush_log_at_trx_commit 的值來(lái)決定以下行為:
- 設(shè)置為 0 的時(shí)候赫冬,表示每次事務(wù)提交時(shí)都只是把 redo log 留在 redo log buffer 中 ;
- 設(shè)置為 1 的時(shí)候,表示每次事務(wù)提交時(shí)都將 redo log 直接持久化到磁盤赊堪;
- 設(shè)置為 2 的時(shí)候面殖,表示每次事務(wù)提交時(shí)都只是把 redo log 寫到 page cache。InnoDB 有一個(gè)后臺(tái)線程哭廉,每隔 1 秒脊僚,就會(huì)把 redo log buffer 中的日志,調(diào)用 write 寫到文件系統(tǒng)的 page cache遵绰,然后調(diào)用 fsync 持久化到磁盤
redo日志的工作就是MySQL意外宕機(jī)重啟時(shí)解析redo log中的事務(wù)后重放一遍辽幌,將Buffer Pool中的緩存頁(yè)重作成臟頁(yè)。后續(xù)再在合適的時(shí)機(jī)將該臟頁(yè)刷入磁盤便可椿访。redo log 值負(fù)責(zé)重做緩沖池的臟頁(yè)數(shù)據(jù)乌企,但是不參與數(shù)據(jù)庫(kù)的落盤工作。數(shù)據(jù)庫(kù)的落盤是將緩沖池中的臟頁(yè)刷到硬盤成玫,而這用到的就checkpoint技術(shù)
checkpoint分為兩種:
第一種是sharp checkpoint加酵,就是在數(shù)據(jù)庫(kù)關(guān)閉時(shí)將緩沖池的臟頁(yè)全部刷到硬盤
第二種是fuzzy checkpoint,fuzzy checkpoint又分為了好幾種checkpoint拳喻,其中包括了master thread checkpoint,它會(huì)執(zhí)行每秒和每十秒的任務(wù)按照一定的比例將臟頁(yè)刷回磁盤中
重做日志緩沖池落盤方式:
1猪腕、MySQL master 線程周期性任務(wù) 每秒一次冗澈,將 redo log buffer 刷新到重作日志中(即使這個(gè)事務(wù)尚未提交)
2、MySQL master 線程周期性任務(wù) 每10秒一次陋葡,將 redo log buffer 刷新到重作日志中
3亚亲、每個(gè)事務(wù)提交時(shí)會(huì)將重做日志緩沖池中相應(yīng)的數(shù)據(jù)刷到重作日志中
4、當(dāng)redo log buffer size 剩余空間小于1/2時(shí)腐缤,將 redo log buffer 刷新到重作日志中
4捌归、當(dāng) redo log file 大小已經(jīng)達(dá)到某個(gè)域值快要"不可用"時(shí)(日志文件組輪流寫文件),觸發(fā) async/sync flush checkpoint岭粤,及時(shí)將緩沖池的一些臟頁(yè)刷新到磁盤惜索,并同時(shí)將redo log buffer刷新到重作日志中。注意:最終落盤是由緩沖池刷到磁盤中剃浇,redo log file不參與落盤的工作门扇。redo日志唯一的工作就是在崩潰恢復(fù)中,InnoDB 如果判斷到一個(gè)數(shù)據(jù)頁(yè)可能在崩潰恢復(fù)的時(shí)候丟失了更新偿渡,就會(huì)將它讀到緩沖池臼寄,然后讓 redo log 更新內(nèi)存內(nèi)容
臟頁(yè)落盤
1、redo log滿了
2溜宽、緩沖池不夠用了吉拳,將對(duì)應(yīng)淘汰的臟頁(yè)寫入硬盤
3、mysql在關(guān)閉時(shí)將臟頁(yè)刷到磁盤
4适揉、mysql在空閑時(shí)啟動(dòng)線程將部分臟頁(yè)落盤
change buffer 和 redo log
當(dāng)需要更新一個(gè)數(shù)據(jù)頁(yè)時(shí)留攒,如果數(shù)據(jù)頁(yè)在內(nèi)存中就直接更新,而如果這個(gè)數(shù)據(jù)頁(yè)還沒有在內(nèi)存中的話嫉嘀,在不影響數(shù)據(jù)一致性的前提下炼邀,InooDB 會(huì)將這些更新操作緩存在 change buffer 中,這樣就不需要從磁盤中讀入這個(gè)數(shù)據(jù)頁(yè)了剪侮。在下次查詢需要訪問這個(gè)數(shù)據(jù)頁(yè)的時(shí)候拭宁,將數(shù)據(jù)頁(yè)讀入內(nèi)存,然后執(zhí)行 change buffer 中與這個(gè)頁(yè)有關(guān)的操作瓣俯。change buffer提升了數(shù)據(jù)庫(kù)修改操作的性能杰标,但是在數(shù)據(jù)寫入change buffer時(shí),也需要往redo log中進(jìn)行寫入
為什么要使用redo log持久化彩匕,直接寫入磁盤不行嗎腔剂?
1、redo log在宕機(jī)時(shí)可以用來(lái)恢復(fù)數(shù)據(jù)
2驼仪、redo log持久化效率高掸犬。數(shù)據(jù)頁(yè)袜漩、索引頁(yè)的刷盤是不容易的,因?yàn)榈讓邮且豢肂+樹結(jié)構(gòu)湾碎。而redo log是順序?qū)懺敕啾葦?shù)據(jù)頁(yè)、索引頁(yè)的直接刷盤要效率高很多
undo log
參考博文:https://www.cnblogs.com/f-ck-need-u/archive/2018/05/08/9010872.html#auto_id_11
概念:
undo用來(lái)回滾行記錄到某個(gè)版本胜茧。undo log是邏輯日志,根據(jù)每行記錄進(jìn)行記錄仇味。undo log有兩個(gè)作用:提供回滾和多個(gè)行版本控制(MVCC)呻顽。
生命周期:
事務(wù)開始之前,將當(dāng)前事務(wù)版本生成 undo log丹墨,undo log 也會(huì)產(chǎn)生 redo log 來(lái)保證 undo log 的可靠性廊遍。當(dāng)事務(wù)提交之后,undo log 并不能立馬被刪除贩挣,而是放入待清理的鏈表喉前,由 purge 線程判斷是否有其它事務(wù)在使用 undo 段中表的上一個(gè)事務(wù)之前的版本信息,從而決定是否可以清理 undo log 的日志空間王财。
存儲(chǔ)內(nèi)容:
undo log 存儲(chǔ)的是邏輯格式的日志卵迂,保存了事務(wù)發(fā)生之前的上一個(gè)版本的數(shù)據(jù),可以用于回滾绒净。當(dāng)一個(gè)舊的事務(wù)需要讀取數(shù)據(jù)時(shí)见咒,為了能讀取到老版本的數(shù)據(jù),需要順著 undo 鏈找到滿足其可見性的記錄挂疆。
存儲(chǔ)位置:
默認(rèn)情況下改览,undo 文件是保存在共享表空間的,也即 ibdatafile 文件中缤言,當(dāng)數(shù)據(jù)庫(kù)中發(fā)生一些大的事務(wù)性操作的時(shí)候宝当,要生成大量的 undo log 信息,這些信息全部保存在共享表空間中胆萧,因此共享表空間可能會(huì)變得很大庆揩,默認(rèn)情況下,也就是 undo log 使用共享表空間的時(shí)候跌穗,被“撐大”的共享表空間是不會(huì)盾鳞、也不能自動(dòng)收縮的。因此瞻离,MySQL5.7 之后的“獨(dú)立 undo 表空間”的配置就顯得很有必要了腾仅。binlog
概念:
MySQL 的二進(jìn)制日志 binlog 可以說是 MySQL 最重要的日志,它記錄了所有的 DDL 和 DML 語(yǔ)句(除了數(shù)據(jù)查詢語(yǔ)句select套利、show等)推励。bin log 的主要目的是復(fù)制和恢復(fù)鹤耍。binlog 用于主從復(fù)制中,從庫(kù)利用主庫(kù)上的 binlog 進(jìn)行重播验辞,實(shí)現(xiàn)主從同步稿黄。用于數(shù)據(jù)庫(kù)的基于時(shí)間點(diǎn)、位點(diǎn)等的還原操作跌造。binlog 的模式分三種:Statement杆怕、Row、Mixed壳贪。
binlog的執(zhí)行過程:
事務(wù)執(zhí)行過程中陵珍,先把日志寫到 binlog cache,事務(wù)提交的時(shí)候违施,再把 binlog cache 寫到 binlog 文件中互纯。系統(tǒng)給 binlog cache 分配了一片內(nèi)存,每個(gè)線程一個(gè)磕蒲,參數(shù) binlog_cache_size 用于控制單個(gè)線程內(nèi) binlog cache 所占內(nèi)存的大小留潦。如果超過了這個(gè)參數(shù)規(guī)定的大小,就要暫存到磁盤辣往。事務(wù)提交的時(shí)候兔院,執(zhí)行器把 binlog cache 里的完整事務(wù)寫入到 binlog 中,并清空 binlogcache
binlog存在write操作和fsync 操作站削。write操作是指的就是指把日志寫入到文件系統(tǒng)的 page cache秆乳,并沒有把數(shù)據(jù)持久化到磁盤,所以速度比較快钻哩。fsync 操作才是將數(shù)據(jù)持久化到磁盤的操作
write 和 fsync 的時(shí)機(jī)屹堰,是由參數(shù) sync_binlog 控制的:
- sync_binlog=0 的時(shí)候,表示每次提交事務(wù)都只 write街氢,不 fsync扯键;
- sync_binlog=1 的時(shí)候,表示每次提交事務(wù)都會(huì)執(zhí)行 fsync珊肃;
- sync_binlog=N(N>1) 的時(shí)候荣刑,表示每次提交事務(wù)都 write,但累積 N 個(gè)事務(wù)后才
fsync伦乔。
因此厉亏,在出現(xiàn) IO 瓶頸的場(chǎng)景里,將 sync_binlog 設(shè)置成一個(gè)比較大的值烈和,可以提升性能爱只。
在實(shí)際的業(yè)務(wù)場(chǎng)景中,考慮到丟失日志量的可控性招刹,一般不建議將這個(gè)參數(shù)設(shè)成 0恬试,比較常
見的是將其設(shè)置為 100~1000 中的某個(gè)數(shù)值窝趣。
更新事務(wù)要寫 binlog,而一旦 binlog 所在磁盤的空間占用率達(dá)到 100%训柴,那么所有的更新語(yǔ)句和事務(wù)提交的 commit 語(yǔ)句就都會(huì)被堵住哑舒。但是,系統(tǒng)這時(shí)候還是可以正常讀數(shù)據(jù)的
binlog的模式
Row 模式
記錄的方式是行幻馁,每一行數(shù)據(jù)的具體變更洗鸵,而不是 SQL 語(yǔ)句,每一條插入仗嗦、更新或刪除操作都會(huì)記錄具體的數(shù)據(jù)行變化膘滨,確保重放時(shí)與原操作完全一致,因此儒将,ROW模式的binlog日志文件會(huì)變得很“重”
優(yōu)點(diǎn):row 模式的binlog日志內(nèi)容會(huì)非常清楚的記錄下每一行數(shù)據(jù)被修改的細(xì)節(jié)。而且不會(huì)出現(xiàn)某些特定情況下存儲(chǔ)過程或function对蒲,以及trigger的調(diào)用和觸發(fā)器無(wú)法被正確復(fù)制的問題钩蚊。
缺點(diǎn):row 模式下,所有執(zhí)行的語(yǔ)句當(dāng)記錄到日志中的時(shí)候蹈矮,都以每行記錄的修改來(lái)記錄砰逻,這樣可能會(huì)產(chǎn)生大量的日志內(nèi)容,產(chǎn)生的binlog日志量是驚人的泛鸟。
Statement 模式(默認(rèn))
記錄的是執(zhí)行的 SQL 語(yǔ)句本身蝠咆,而不是具體的行數(shù)據(jù)變更。
優(yōu)點(diǎn):statement模式記錄的更改的SQ語(yǔ)句事件北滥,并非每條更改記錄刚操,所以大大減少了binlog日志量,節(jié)約磁盤IO再芋,提高性能菊霜。
缺點(diǎn):statement level下對(duì)一些特殊功能的復(fù)制效果不是很好,比如:函數(shù)济赎、存儲(chǔ)過程的復(fù)制鉴逞。由于row level是基于每一行的變化來(lái)記錄的,所以不會(huì)出現(xiàn)類似問題
Row 與Statement 的區(qū)別
Mixed 模式
實(shí)際上就是Statement與Row的結(jié)合司训。
在Mixed模式下构捡,一般的語(yǔ)句修改使用statment格式保存binlog,如一些函數(shù)壳猜,statement無(wú)法完成主從復(fù)制的操作勾徽,則采用row格式保存binlog,MySQL會(huì)根據(jù)執(zhí)行的每一條具體的sql語(yǔ)句來(lái)區(qū)分對(duì)待記錄的日志形式统扳,也就是在Statement和Row之間選擇一種捂蕴。
如何選擇binlog的模式
1譬涡、 如果生產(chǎn)中使用MySQL的特殊功能相對(duì)少(存儲(chǔ)過程、觸發(fā)器啥辨、函數(shù))涡匀。選擇默認(rèn)的語(yǔ)句模式,Statement Level溉知。
2陨瘩、 如果生產(chǎn)中使用MySQL的特殊功能較多的,可以選擇Mixed模式级乍。
3舌劳、 如果生產(chǎn)中使用MySQL的特殊功能較多,又希望數(shù)據(jù)最大化一致玫荣,此時(shí)最好Row level模式甚淡;但是要注意,該模式的binlog非惩背В“沉重”贯卦。
查看binlog模式
mysql> show global variables like "%binlog_format%";
+---------------+-----------+
| Variable_name | Value |
+---------------+-----------+
| binlog_format | STATEMENT |
+---------------+-----------+
配置binlog日志模式
vim my.cnf
log-bin = /data/3306/mysql-bin
binlog_format="STATEMENT"
#binlog_format="ROW"
#binlog_format="MIXED"
生命周期:
事務(wù)提交的時(shí)候,一次性將事務(wù)中的 sql 語(yǔ)句(一個(gè)事務(wù)可能對(duì)應(yīng)多個(gè) sql 語(yǔ)句)按照一定的格式記錄到 binlog 中焙贷,這里與 redo log 很明顯的差異就是 redo log 并不一定是在事務(wù)提交的時(shí)候才刷新到磁盤撵割,而是在事務(wù)開始之后就開始逐步寫入磁盤。binlog 的默認(rèn)保存時(shí)間是由參數(shù) expire_logs_days 配置的辙芍,對(duì)于非活動(dòng)的日志文件啡彬,在生成時(shí)間超過 expire_logs_days 配置的天數(shù)之后,會(huì)被自動(dòng)刪除故硅。
日志文件:
binlog日志包括兩類文件:
1庶灿、二進(jìn)制日志索引文件(文件名后綴為.index)用于記錄所有有效的的二進(jìn)制文件