Mysql 百問系列:redo log 作什麼用?

Mysql 百問系列:redo log 作什麼用?

問題redo log 由來爲何redo log 的信息在崩潰的時候不會丟失?redo log bufferCheckpoint總結系列文章web

問題

  • 爲何要設計redo log?
  • 什麼又是redo log buffer ?
  • 什麼是checkpoint?

redo log 由來

引入了Buffer Pool 以後的確給數據的讀寫提高了效率。固然也同時帶來了問題。
列如:
個人帳戶餘額有200塊錢,發工資那天公司匯進來5000塊錢。sql

update account set price = 5200 where id = 24
複製代碼

咱們知道執行更新後,數據只是放在Buffer Pool 中,磁盤文件中仍是老數據。但是恰恰倒黴,這時候服務器斷電了,內存中的數據一會兒就沒有了。這可怎麼辦?到手的工資跑了。
固然了,Mysql 是不容許這種事情發生的,已經提交的事務,必須具備持久化能力。也就是針對上述狀況,Mysql 必須保證更新語句若是成功,那麼後續發生電點,崩潰等狀況,服務器重啓後數據還是修改完成後的數據。
爲了作到這一點redo log 誕生了。能夠說redo log爲InnoDB 提供了可持久化的能力。
有了redo log ,上面的更新流程就變成了:數據庫

  1. 修改Buffer Pool 對應頁中的信息。(假設頁已經存在在Buffer Pool中)
  2. 新增redo log 記上一筆:把id=24 的帳戶的餘額改成5200。 (固然實際狀況可能還要複雜,好比要記錄索引等等其餘修改,順帶一條redo log 日誌的類型在Mysql 5.7.21中有53種之多)
  3. 返回更新結果

這樣,即便修改完成後,Buffer Pool 中的數據來不及刷入磁盤,數據庫重啓之時,仍是能夠從redo log 中讀取修改的內容,從新再作一遍一樣的操做(redo)。保證了Buffer Pool 中的數據丟失還能找回來。服務器

爲何redo log 的信息在崩潰的時候不會丟失?

redo log 是存放在磁盤的。app

  • innodb_log_group_home_dir 指定redo日誌文件存放的目錄。
  • innodb_log_file_size 指定每一個redo日誌文件的大小。
  • innodb_log_files_in_group 指定redo日誌的個數

redo log 能夠存放的空間爲:innodb_log_file_size × innodb_log_files_in_grouppost

那麼問題來了,咱們知道Buffer Pool 是經過減小磁盤操做,從而提高性能的。如今爲了保證持久性,寫入redo log 仍是要進行磁盤操做,這樣不是白費力了嗎?
redo log 要進行磁盤操做這個是不可避免的,可是與Buffer Pool 磁盤隨機寫入比, redo log 的磁盤操做有幾個優點: 1. 引入redo log buffer,按組寫入,不是一條條寫。 2. 磁盤爲順序寫入。
固然也能夠記住結論就是 redo log 日誌的磁盤操做比起 Buffer Pool 的磁盤操做 性能要好不少。

redo log buffer

照搬Buffer Pool 的原理,redo log 也不是直接寫入磁盤的,redo log 會先寫入 redo log buffer 中,而後再寫入磁盤。 那麼問題又又又來了,怎麼保證redo log buffer 中的信息在崩潰的時候不會丟失呢?
redo log buffer 的刷盤時機:性能

  • redo log buffer 空間不足的時候。
  • 事務提交的時候
  • 後臺線程在不停的刷
  • 服務正常關閉的時候
  • checkpoint的時候

(能夠比較下Buffer Pool 的刷盤時機,看看二者有什麼不一樣有什麼相同)
從刷盤時機來看,redo log buffer的刷盤時機更爲頻繁,尤爲是事務提交的時候這一條保證了提交的事務redo log 就已經存儲到了磁盤中。
innodb_flush_log_at_trx_commit 取值範圍 0,1,2
這個變量是用來控制事務提交的時候是否要刷新redo log buffer 到磁盤中。
0:標識事務提交不會向磁盤同步redo log。
1:默認值,每次提交事務向磁盤同步redo log。
2:每次提交事務將redo log 寫到操做系統的緩衝區中,但沒有真正寫入磁盤。
這三種方式都各有利弊:
0: 雖然說按組批量順序寫入磁盤提升了很多磁盤操做效率,可是終歸仍是有點性能損耗的,把變量設置成0,那麼事務提交的時候就徹底避免了磁盤操做, 交由後臺線程去刷新磁盤。 這樣在大量頻繁修改的業務場景的可以提高性能,可是一樣要面對服務器掛了有數據丟失的風險。
1: 性能不如0,可是保證了提交的事務數據不丟失。
2: 性能介於0,1之間。能保證若是操做系統沒掛,數據庫掛了,事務的持久性還能保證,可是若是操做系統也掛了數據就會丟失。
(根據業務場景和服務器配置挑選合適的innodb_flush_log_at_trx_commit也能提高性能)spa

Checkpoint

上面已經提到redo log 的空間是有限的,例如咱們定義每一個文件大小爲1G,文件數量爲2個,那麼redo log 最多能存儲2G 大小的內容。因此會存在一種狀況:修改內容較多,且事務持續時間很長(所謂的大事務),就會致使redo log 寫滿而沒法寫入。
在通常狀況下,redo log 又是怎麼工做的呢?
redo log 是一個環,經過擦除沒用的信息達到空間的重複利用。 具體實現過程比較複雜,我這邊只介紹下核心的思想,對具體實現有興趣的朋友能夠看 掘金小冊:MysSQL是怎麼運行的 第22章
什麼是沒用的信息呢?
咱們知道redo log 是爲了防止Buffer Pool中的髒頁丟失而設計的,那麼若是隨着系統運行,Buffer Pool 的髒頁刷新到了磁盤中,那麼redo log 對應的記錄也就沒用了。 一次checkpoint 的過程就是髒頁刷新到磁盤中變成乾淨頁,而後標記redo log 哪些記錄能夠被覆蓋的過程。操作系統

總結

  • redo log 使用來保證InnoDB 的持久性的。
  • redo log 是保存在磁盤文件中的,可是經過按組,順序寫入的方式提高磁盤IO效率
  • redo log buffer 向磁盤刷入的時機更爲頻繁。能夠經過innodb_flush_log_at_trx_commit控制事務提交是否刷盤。
  • redo log 因爲空間有限,因此經過一次次的checkpoint 來標記能夠覆蓋的空間信息。

系列文章

Mysql 百問系列 : Join 會有哪幾種工做方式?
Mysql 百問系列:Buffer Pool 是什麼?線程

喜歡,支持歡迎關注公衆號

相關文章
相關標籤/搜索