白日夢感受做爲研發同窗的你可能真的不必瞭解摸清楚關於redo log的這些機制。專一於寫SQL徹底能hold住平常的工做。html
可是呢,感受最好仍是要了解一下,由於通常面試官都知道redo log是咋回事,其次是你們茶前飯後嘮嗑時也能多少能插幾句嘴。前端
文章公號 首發!連載中!關注微信公號回覆:「抽獎」 還可參加抽📖活動
mysql
繼續咱們的MySQL專題。首先回顧一下前面白日夢同你分享過的知識點。面試
前面咱們一塊兒學習了MySQL undo log相關的知識點,看下面這張腦圖:sql
磁盤上的數據文件叫表空間文件,表空間有挺多的,好比系統表空間、undo log 表空間、你也可讓create出來的每張table都有本身單獨的表空間。總之MySQL會將表空間數據頁經過磁盤IO加載進緩存頁中。數據庫
SQL執行器會執行你發送給MySQL的SQL語句,MySQL爲了提升的性能,對於增、刪、改這種操做都是在內存中完成的,所謂的內存就是上圖中BufferPool。好比上圖中的SQL執行器執行了一條update xxx where id = 1語句,而後這個id = 1數據行所在的數據頁就會被你修改爲髒數據頁。緩存
此外MySQL還有專門的後臺線程等其餘機制負責將髒數據頁刷新同步回磁盤。安全
你能夠結合上圖而後想一下:萬一髒頁還沒來得及刷新到磁盤中,MySQL就掛了,怎麼辦呢?微信
對於業務代碼來講,方纔執行的事務是OK的,甚至前端都接受到了請求成功的響應。那結果修改的數據沒同步回磁盤,MySQL宕機了會不會致使真實數據和邏輯上的數據不一致呢?性能
其實不會的!
MySQL使用redo log解決了這個問題,redo故名思義:重作。
當發生事務(增、刪、改)時會致使緩存頁變成髒頁,於此同時MySQL會將事務涉及到的:對 XXX表空間中的XXX數據頁XXX偏移量的地方作了XXX更新。
因此MySQL意外宕機重啓也不要緊。只要在重啓時解析redo log中的事務而後重放一遍。將Buffer Pool中的緩存頁重作成髒頁。後續再在合適的時機將該髒頁刷入磁盤便可。
因而對於業務方來講,everything is ok!
redo log側重於重作!redo log中記錄的是物理層面的數據頁、偏移量。應對的問題是:MySQL異常宕機後,如何將沒來得及提交的事物數據重作出來。
然後面文章中和你們分享的bin log中記錄了你對XXX表條件爲XXX處的數據做了什麼修改,這是些都是邏輯上的概念。
首先你得知道,redo並非一條條直接寫入磁盤中去的!
在MySQL的設定中,redolog是按塊,一塊一塊的寫入到磁盤中去的。
你能夠類比一下數據是按頁爲單位來組織的,就更容易理解爲啥redo log 要按照block來組織redo。
本質上就是兩個字:優化
log block長成下面這這樣:分紅Header、Body、Trailer三部分 總共512字節。並且是覆蓋寫入。
我粗略解讀一下這幅腦圖。
首先既然MySQL會寫redo log,說明你的sql會對緩存頁形成修改,也就意味着會走MySQL設定的事物那一套機制。既然是MySQL事物,大機率就是一組增、刪、改。若是每一個增、刪、改都會有一個對應的redo log的話,那也就是說你的事物會產生好多redolog。這些redo會先被持續不斷的寫入到log block中,同一個事物產生的redo log會被標記爲一個redo log group。
瞭解redo log block以後,白日夢還要跟你介紹一下 redo log buffer。
這個redo log buffer 中會劃分出多個rodo log block。redo log buffer 佔用一塊連續的內存空間,默認大小16MB。且MySQL容許咱們經過參數innodb_log_buffer_size
動態的調整它。增大它的大小可讓MySQL處理大事物是沒必要寫入磁盤。進而提高寫IO性能。
引入rodo log buffer以後,就能夠勾勒出這樣一副腦圖。
如圖,產生的redo log 先寫入redo log block。而後redo log block其實就在redo log buffer 中。
看到這裏不知道你有沒有想到這樣一個問題:redo log buffer再怎麼神奇畢竟也是僅僅在內存中,此時萬一MySQL宕機了怎麼辦?redolog-buffer中的數據丟失了怎麼辦?畢竟沒有寫到磁盤上,MySQL重啓後100%沒辦法將其恢復出來。
其實你並不用擔憂這種狀況!
由於在MySQL的設定中,當你要Commit事務時,redolog纔會持久化進磁盤,既然你沒有commit,碰巧MySQL又宕機了。那讓MySQL正常重啓就行了啊,反正你沒有commit,MySQL也也沒有必要幫你恢復什麼。
那 redo log buffer 什麼時候寫入磁盤呢?
innndb_log_buffer_size
的一半時,會觸發落盤。承接上面描述的場景:事務提交時,率先將redo log持久化進磁盤。
那你如何控制MySQL,讓MySQL在Commit事務時率先將redo log持久化呢?
MySQL提供了參數innodb_flush_log_at_trx_commit
該參數有幾個選項:0、一、2
想要保證ACID四大特性推薦設置爲1:表示當你commit時,MySQL必須將rodolog-buffer中的數據刷新進磁盤中。確保只要commit是成功的,磁盤上就得有對應的rodolog日誌。這也是最安全的狀況。
設置爲0:每秒寫一第二天志並將其刷新到磁盤。
設置爲2:表示當你commit時,將redolog-buffer中的數據刷新進OS Cache中,而後依託於操做系統每秒刷新一次的機制將數據同步到磁盤中,也存在丟失的風險。
始終設置 innodb_flush_log_at_trx_commit=1
若是啓用了二進制日誌記錄,請設置 sync_binlog=1
。
這也是你們常說的雙1設置。前者保證redolog的不丟失、後者保證了binlog的不丟失。
關於sync_binlog參數,計劃在第X、X、篇文章中分享binlog知識點的時候會再說起,歡迎關注!
redo log group說的是:由N個大小相同的redo log組成一個redo log group。N的值默認爲2。
你能夠像下面這樣查看你的MySQL的redo log group狀況。
默認單個redo log文件的大小是48MB。你也能夠經過上圖中的innndb_log_files_size
修改它。
日誌文件的總大小(innodb_log_file_size* innodb_log_files_in_group)不能超過略小於512GB的最大值。
例如,一對255 GB的日誌文件已達到限制,但沒有超過該限制。
一樣你能夠像下面這樣查看磁盤上的 redo log 文件。它們的大小和上圖中的innodb_log_file_size相同。
innodb將log buffer中的redo log block刷新到上圖中的logfile中時,以追加的方式循環寫入。也就是首先在ib_logfile0的尾部追加,寫滿後再寫ib_logfile1。當ib_logfile1寫滿時,狀況一部分ib_logfile0接着追加寫。
redo log file的大小對innodb性能影響很是大。一般來講要設置的足夠大,大到可讓MySQL支持1小時線上高峯流量的接入而不切換。可是設置的過大,數據恢復的時間比較長。設置太小致使循環切換redo log file。
能聊聊:日誌刷盤規則之 check point 和 LSN機制嗎?
參考:
https://dev.mysql.com/doc/refman/5.7/en/innodb-redo-log.html
https://dev.mysql.com/doc/refman/5.7/en/replication-solutions-unexpected-replica-halt.html
https://dev.mysql.com/doc/refman/5.7/en/innodb-init-startup-configuration.html
https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit
https://dev.mysql.com/doc/refman/5.7/en/innodb-init-startup-configuration.html
文章公號 首發!連載中!關注微信公號回覆:「抽獎」 還可參加抽📖活動