談談傳說中的redo log是什麼?有啥用?

白日夢感受做爲研發同窗的你可能真的不必瞭解摸清楚關於redo log的這些機制。專一於寫SQL徹底能hold住平常的工做。html

可是呢,感受最好仍是要了解一下,由於通常面試官都知道redo log是咋回事,其次是你們茶前飯後嘮嗑時也能多少能插幾句嘴前端

文章公號 首發!連載中!關注微信公號回覆:「抽獎」 還可參加抽📖活動
mysql

1、引出 redo log 的做用

繼續咱們的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還有專門的後臺線程等其餘機制負責將髒數據頁刷新同步回磁盤。安全


2、思考一個問題:

你能夠結合上圖而後想一下:萬一髒頁還沒來得及刷新到磁盤中,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處的數據做了什麼修改,這是些都是邏輯上的概念。


3、redo log block

首先你得知道,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。


4、redo log buffer

瞭解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 什麼時候寫入磁盤呢?

  1. 事物提交時把它對應的那些redo log寫入到磁盤中去(這個動做可由相關參數控制,下文會說)
  2. 當redo log buffer 使用量達到了參數innndb_log_buffer_size的一半時,會觸發落盤。
  3. 會有一個後臺線程,每隔1秒就會將redo log block刷新到磁盤文件中去。
  4. MySQL關閉時也會將其落盤。

5、redo log的刷盤時機

承接上面描述的場景:事務提交時,率先將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中,而後依託於操做系統每秒刷新一次的機制將數據同步到磁盤中,也存在丟失的風險。


6、推薦參數

  • 始終設置 innodb_flush_log_at_trx_commit=1

  • 若是啓用了二進制日誌記錄,請設置 sync_binlog=1

這也是你們常說的雙1設置。前者保證redolog的不丟失、後者保證了binlog的不丟失。

關於sync_binlog參數,計劃在第X、X、篇文章中分享binlog知識點的時候會再說起,歡迎關注!


7、redo log group

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


推薦閱讀

  1. 你們常說的基數是什麼?(已發佈)
  2. 講講什麼是慢查!如何監控?如何排查?(已發佈)
  3. 對NotNull字段插入Null值有啥現象?(已發佈)
  4. 能談談 date、datetime、time、timestamp、year的區別嗎?(已發佈)
  5. 瞭解數據庫的查詢緩存和BufferPool嗎?談談看!(已發佈)
  6. 你知道數據庫緩衝池中的LRU-List嗎?(已發佈)
  7. 談談數據庫緩衝池中的Free-List?(已發佈)
  8. 談談數據庫緩衝池中的Flush-List?(已發佈)
  9. 瞭解髒頁刷回磁盤的時機嗎?(已發佈)
  10. 用十一張圖講清楚,當你CRUD時BufferPool中發生了什麼!以及BufferPool的優化!(已發佈)
  11. 據說過表空間沒?什麼是表空間?什麼是數據表?(已發佈)
  12. 談談MySQL的:數據區、數據段、數據頁、數據頁究竟長什麼樣?瞭解數據頁分裂嗎?談談看!(已發佈)
  13. 談談MySQL的行記錄是什麼?長啥樣?(已發佈)
  14. 瞭解MySQL的行溢出機制嗎?(已發佈)
  15. 說說fsync這個系統調用吧! (已發佈)
  16. 簡述undo log、truncate、以及undo log如何幫你回滾事物! (已發佈)
  17. 我勸!這位年輕人不講MVCC,耗子尾汁! (已發佈)


文章公號 首發!連載中!關注微信公號回覆:「抽獎」 還可參加抽📖活動

相關文章
相關標籤/搜索