MySQL中的redo log和checkpoint

lff1530983327發表於2022-10-09
提到MySQ中的checkpoint就不得不提redo log了。
下面跟隨筆者一起來梳理一下REDO LOG相關知識點吧!
問題點:
1.checkpoint發生的時間點是什麼時候?
2.checkpoint的作用是什麼?
3.為什麼有那麼多資料庫架構選擇去掉checkpoint這一機制呢?比如 AWS的Aurora(MySQL)?

1.redo log日誌型別

redo log日誌還是有點意思,竟然根據寫入大小來劃分型別, 諸如:MLOG_1BYTE、 MLOG_8BYTE等。當然,這只是簡單型redo ,還有複雜一些的型別, 諸如:MLOG_COMP_REC_INSERT表示插入一條使用緊湊行格式的記錄時的redo日誌型別。每組redo log日誌最後一條日誌型別為MLOG_MULTI_REC_END,表示redo log是完整的。 對底層頁面的一次原子訪問稱之為Mini-Transaction,一個包含多條語句的事務,每個事物含有多個原子性操作,會產生一組mini-trx。 各組mini-trx在log buffer中是交替寫入的。mtr執行中產生的一組redo log會在mtr結束的時候複製到log buffer中。
注意: 在MySQL5.7之後還新增了幾條redo log型別,如:MLOG_CHECKPOINT、MLOG_FILE_NAME ,其中MLOG_CHECKPOINT在MySQL8.0之後被廢棄了,這裡可以將MLOG_CHECKPOINT算著是MLOG_FILE_NAME的一種補充,可以簡單理解為 MLOG_FILE_NAME是為了在做Crash recovery的時候將查詢需要恢復的表的ibd檔案的過程與資料字典解耦,透過查詢MLOG_FILE_NAME型別的redo log找到後續需要恢復的space資訊。MLOG_CHECKPOINT則是對MLOG_FILE_NAME的一種補充,在系統檢查點之後,對當前活動的所有資料檔案做一個MLOG_FILE_NAME的補全,完成之後,寫入MLOG_CHECKPOINT。Crash recovery的時候,碰到MLOG_CHECKPOINT則表示在它之前,檢查點之後的所有redo log和space的對映關係均已建立完成。如果沒有找到MLOG_CHECKPOINT則表示系統是正常關閉,checkpoint之後無髒頁。

2.redo log日誌的內部結構

redo log 是以512位元組大小 的block進行記錄的,log檔案的前2048個位元組,也就是前4個block包含有file header、checkpoint1、checkpoint2,其中file header中會記錄log file檔案開始的LSN,checkpoint則記錄有伺服器做checkpoint的編號,伺服器做checkpoint時候的LSN,checkpoint時候LSN值對應的日誌檔案的偏移量。flush連結串列中的髒頁就是按照髒頁最先修改發生時候的LSN進行連線和排序的,除此之外還記錄有最近一次修改LSN。

3.log buffer 刷盤時機

容量超過log buffer的一半
每次事務提交時(innodb_flush_log_at_trx_commit)
髒頁刷盤前
後臺執行緒,大概1s一次
正常關閉伺服器
checkpoint
binlog切換

4.checkpoint

buffer pool中的髒頁在沒有flush 到盤之前是不能進行其對應位置的redo log的覆蓋使用的,checkpoint_Lsn表示可以被覆蓋的redo log的位點。
checkpoint_no、checkpoint_lsn、checkpoint_offset為日誌管理資訊,當checkpoint_no為偶數時,寫入checkpoint_1,奇數時候,寫入checkpoint_2中。
checkpoint發生分為fuzzy_checkpoint和sharp_checkpoint。
fuzzy_checkpoint是在例項執行時,以一定的比例進行刷髒。
分為Master thread checkpoint
Flush_lru_list(innodb_lru_scan_depth)
Async/sync checkpoint(redo日誌檔案大小不夠用)
髒頁太多,超過innodb_max_dirty_pages_pct。
sharp_checkpoint則發生在例項關閉的時候。

 

5.崩潰恢復的兩個LSN點

恢復的起點為checkpoint_lsn,崩潰恢復的終點為log block中LOG_BLOCK_HDR_DATA_LEN<>512de 塊。 在這checkpoint_lsn之前的髒頁肯定是被flush到磁碟的,在這之後的髒頁呢?不一定沒有刷到磁碟,如果某個髒頁在checkpoint之後被刷盤,那麼這個頁面header中的FIL_PAGE_LSN一定大於checkpoint_lsn,符合這種情況的頁中LSN小於該值的redo log也是不需要進行恢復的。

6.redo log 檔案最大是多少?

在初次使用一個log block的時候會分配一個LOG_BLOCK_HDR_NO,記錄在log block header處,計算公式為 ((lsn / 512) & 0x3FFFFFFFUL) + 1,最多產生1GB個LOG_BLOCK_HDR_NO,redo日誌檔案組中包含的所有檔案大小不超過512G。

7.關於redo log的版本最佳化

7.1 To simplify InnoDB tablespace discovery during crash recovery, new redo log record types were introduced in MySQL 5.7.5. This enhancement changes the redo log format。

7.2 From MySQL 8.0.30, the [innodb_redo_log_capacity]variable controls the amount of disk space occupied by redo log files.InnoDB maintains 32 redo log files in the #innodb_redo directory in the data directory.the [innodb_log_files_in_group]and [innodb_log_file_size]variables. These two variables are now deprecated.

7.3 在高併發的環境中,mtr需要複製至log buffer中,MySQL8.0開始,允許不同的mtr併發的寫入log buffer。

8.redo log刷盤的過程

redo log 主要為ACID中的D服務,要求其在事務提交之前,寫完。寫redo log的過程包括一開始由mtr_start生成的mtr。mtr中會動態維護一個動態增長的m_log,原子操作需要寫的所有REDO先寫到這個m_log中,原子操作結束後,mtr_commit會將m_log中的資料複製至Log Buffer中。 寫入Log Buffer中的redo 需要進一步寫入作業系統的Page Cache,由log_write來完成。(MySQL8.0併發mtr寫入導致的空洞問題,由link_buffer的資料結構解決)。 寫入Log Buffer之後便是flush過程,log_flusher執行緒會呼叫fsync完成刷盤,當然,這個過程還會有 innodb_flush_log_at_trx_commit引數的介入。
0 log are writen and flushed to disk once per second
1 writen and flushed to disk at each trx commit
2 log are writen afetr each trx commit and flushed to disk once per second

 

9.相關引數

9.1  innodb_redo_log_capacity

當設定了 innodb_redo_log_capacity該引數,那麼 innodb_log_files_in_group    innodb_log_file_size  將會被忽略。最大512G。

innodb_log_files_in_group  *  innodb_log_file_size  =  innodb_redo_log_capacity

9.2 innodb_log_file_size  and  innodb_log_files_in_group  

They are deprecated in MySQL 8.0.30。

9.3  innodb_log_group_home_dir

The directory path to the  InnoDB   redo log  files.


問題解答

1.checkpoint發生的時間點是什麼時候?

分fuzzy checkpoint和sharp checkpoint兩種
 
2.checkpoint的作用是什麼?
checkpoint其實並不像後臺程式那樣,會有一定的flush或者fsync的操作,只是檢查buffer pool中最老的髒塊的lsn是什麼,並且記錄。其他的工作還是依賴後臺程式去做。
Makes a checkpoint. Note that this function does not flush dirty blocks from the buffer pool. It only checks what is lsn of the oldest modification

in the buffer pool, and writes information about the lsn in log files 


3.為什麼有那麼多資料庫架構選擇去掉checkpoint這一機制呢?比如 AWS的Aurora(MySQL)?
 Aurora實行的是Log is database,它的寫入是沒有資料頁的概念的,只是redo log在流轉,所以這個過程中不需要checkpoint去標識哪些頁已經落盤,哪些頁沒有。
 
參考:
[MySQL 是怎樣執行的:從根兒上理解 MySQL]
庖丁解InnoDB之REDO LOG
https://cloud.tencent.com/developer/article/1506059


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30018455/viewspace-2917397/,如需轉載,請註明出處,否則將追究法律責任。

相關文章