欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MySQL redo日志寫入磁盤的實現過程

 更新時間:2025年06月26日 09:02:59   作者:在成都搬磚的鴨鴨  
這篇文章主要介紹了MySQL redo日志寫入磁盤的實現過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

1、背景

之前我們講過redo日志類型有很多種,但是要想保證服務器崩潰數據能還原,這些日志還是得存儲在磁盤上,接下來我們就來講解一下redo日志的存儲過程。

2、redo日志存儲過程

【1】redo log block

redo日志也是存儲在頁中的,頁的大小為512字節(jié),存儲redo日志的頁就被稱為redo log block,一個redo log block有三部分組成,其組成如圖:

在這里插入圖片描述

字段含義如下:

字段名字節(jié)大小含義
log block header12由4部分組成,存儲管理信息
log block body496真正存儲redo日志數據的地方
log block trailer4由1部分組成,用于校驗正確性

log block header的組成結果如圖:

在這里插入圖片描述

字段含義如下:

字段名字節(jié)大小含義
LOG_BLOCK_HDR_NO4每個block的唯一編號
LOG_BLOCK_HDR_DATA_LEN2block中已經使用了多少字節(jié),初始就為log block header大小12
LOG_BLOCK_FIRST_REC_GROUP2這個block中第有個mtr(Mini-Transaction)對應的redo日志組中第一條redo日志偏移量
LOG_BLOCK_CHECKPOINT_NO4checkpoint序號

【2】log buffer

redo日志也不是直接寫入磁盤,會寫入一塊連續(xù)的內存區(qū)域,這塊連續(xù)的內存就叫log buffer,其結構如圖:

在這里插入圖片描述

這塊連續(xù)內存的大小可以通過innodb_log_buffer_size字段查看,單位字節(jié):

mysql> show VARIABLES LIKE 'innodb_log_buffer_size';
+------------------------+----------+
| Variable_name          | Value    |
+------------------------+----------+
| innodb_log_buffer_size | 16777216 |
+------------------------+----------+
1 row in set, 1 warning (0.00 sec)

【3】buf_free

一個事務可以有多個mtr,一個mtr可以有多個redo日志記錄,將redo日志寫入log buffer中時,時間上是寫入block中的log block body部分,當一個block寫滿也就是log block body寫滿時,就去寫連續(xù)的下一個block,可以寫入redo日志的空閑log buffer的最小偏移量就叫buf_free,所以每次我們要寫入redo日志只需要找到buf_free偏移量,就可以知道在log buffer的哪個地方寫redo日志了,可以如圖表示:

在這里插入圖片描述

【4】redo日志刷盤時機

log buffer空閑有限,所以也需要將redo日志寫到磁盤再釋放空間,用于寫入新的redo日志,從內存刷到磁盤的時機有如下幾種:

  • 1、log buffer空間不足
  • 2、事務提交時
  • 3、后臺線程定時刷
  • 4、正常關閉服務器
  • 5、checkpoint時

【5】redo日志文件組

從log buffer刷新到磁盤中的redo日志是存儲在ib_logfile0、ib_logfile1、ib_logfilen文件中,這些文件就叫redo日志文件組,可以通過配置文件指定此組文件的目錄、大小、數量。

查看目錄方式如下:

mysql> show VARIABLES LIKE 'innodb_log_group_home_dir';
+---------------------------+--------------------------------------------+
| Variable_name             | Value                                      |
+---------------------------+--------------------------------------------+
| innodb_log_group_home_dir | /xxx/data |
+---------------------------+--------------------------------------------+
1 row in set (0.002 sec)

查看大小方式如下,單位字節(jié):

mysql> show VARIABLES LIKE 'innodb_log_file_size';
+----------------------+----------+
| Variable_name        | Value    |
+----------------------+----------+
| innodb_log_file_size | 50331648 |
+----------------------+----------+
1 row in set, 1 warning (0.01 sec)

查看數量方式如下:

mysql> show VARIABLES LIKE 'innodb_log_files_in_group';
+---------------------------+-------+
| Variable_name             | Value |
+---------------------------+-------+
| innodb_log_files_in_group | 2     |
+---------------------------+-------+
1 row in set, 1 warning (0.00 sec)

查看一下ib_logfile文件如下:

[root@xxx xxx]# ls /xxx/data/ | grep 'ib_log'
ib_logfile0
ib_logfile1

寫文件是ib_logfile0到ib_logfile1循環(huán)寫入,當ib_logfile1寫滿時就重新從ib_logfile0重新寫入。

【6】ib_logfile文件格式

和log buffer的組成結構一樣,ib_logfile也是由連續(xù)的512字節(jié)大小的block組成,有區(qū)別的是ib_logfile的前四個block用了存儲管理信息,后面的block才用來存儲redo日志,其存儲過程可以如圖表示:

在這里插入圖片描述

redo日志文件前四個block分別為log file header、checkpoint1、未使用、checkpoint2,checkpoint1和checkpoint2是一樣的,接下來我們就來講一下log file header和checkpoint。

log file header結構如下:

在這里插入圖片描述

其字段含義為:

字段字節(jié)大小含義
LOG_HEADER_FORMAT4redo日志版本
LOG_HEADER_PAD14無用
LOG_HEADER_START_LSN8標記redo日志文件開始的LSN值,也就是第5個block開始對應的LSN值
LOG_HEADER_CREATOR32標記redo日志的創(chuàng)建者
LOG_BLOCK_CHECKSUM4本block的校驗值

checkpoint結構如下:

在這里插入圖片描述

其字段含義為:

字段字節(jié)大小含義
LOG_CHECKPOINT_NO8服務器每做一次checkpoint,該值就加1
LOG_CHECKPOINT_LSN8服務器做checkpoint結束時對應的LSN值,系統崩潰恢復時從該值開始
LOG_CHECKPOINT_OFFSET8上個屬性中LSN值在redo日志文件組中的偏移量
LOG_CHECKPOINT_LOG_BUF_SIZE8服務器在做checkpoint時對應的log buffer大小
LOG_BLOCK_CHECKSUM4block的校驗值

【7】Log Sequeue Number

log buffer中,InnoDB為已經寫入的redo日志量用個全局變量Log Sequeue Number表示,也叫日志序列號,簡稱lsn,lsn的初始值為8704,但是block真正寫redo日志的是中間的body部分,所以初始的lsn值需要加上第一個block的log block header(12字節(jié))的大小得到初始的lsn值為8716,需要注意后續(xù)寫入的redo日志如果占用了幾個block,計算lsn就需要加上log block header和log block trailer。

【8】flushed_to_disk_lsn

lsn是標記log buffer中已經寫入redo日志的量,不關心log buffer上的redo日志是否刷新到磁盤上也就是ib_logfile中,所以InnoDB中提供了flushed_to_disk_lsn的全局變量來標識log buffer中已經被刷到磁盤的量。

【9】flush鏈表中的lsn

當我們修改一條數據可能會產生以下流程,首先會產生多個mtr,將這些mtr對應的redo日志組寫到log buffer中,然后修改buffer pool中的頁,最后再將修改的頁對應的控制塊加入flush鏈表,控制塊中有個兩個記錄lsn的屬性,oldest_modification和newest_modification,其屬性含義如下:

屬性名含義
oldest_modification控制塊對應的頁被修改起始對應的lsn值
newest_modification控制塊對應的頁被修改結束對應的lsn值

需要注意的是多個mtr修改相同的頁,不會修改頁對應的控制塊在鏈表中的位置,但是會更新newest_modification屬性的值。

【10】checkpoint

InnoDB中提出了一個全局變量checkpoint_lsn,用來表示redo日志文件中小于該值的部分都可以被覆蓋,checkpoint指的是buffer pool中的臟頁被刷新到磁盤,這時臟頁對應的redo日志就可以被覆蓋了,我們就能計算一個checkpoint_lsn值這個過程。

InnoDB中還有一個checkpoin_no的變量,每執(zhí)行一次checkpoint,該值就會加1。

前面講過checkpoint的屬性就會包含:checkpoint_lsn、checkpoint_no、checkpoint_lsn對應的偏移量,至于這些屬性是存儲在checkpoint1還是checkpoint2中,是根據checkpoint_no是奇數還是偶數,如果是奇數就寫到checkpoit2中,偶數就寫checkpoint1中。

【11】系統中的LSN值

我們可以查看系統中的lsn值,可以通過如下命令去查看:

mysql> show engine innodb status\G;
...
---
LOG
---
Log sequence number          20993334
Log buffer assigned up to    20993334
Log buffer completed up to   20993334
Log written up to            20993334
Log flushed up to            20993334
Added dirty pages up to      20993334
Pages flushed up to          20993334
Last checkpoint at           20993334
Log minimum file id is       6
Log maximum file id is       6
25 log i/o's done, 0.00 log i/o's/second
...

其字段含義為:

字段名含義
Log sequence number當前redo日志中LSN的最大值,表示所有修改數據的操作產生的日志序列號,該值會隨著日志的寫入逐漸增大
Log buffer assigned up tolog buffer中被分配到的lsn值,與Log sequence number相同
Log buffer completed up tolog buffer中準備好寫磁盤的lsn值,與Log sequence number相同
Log written up to已經寫到redo日志文件的日志序列號
Log flushed up to已經刷新到磁盤的redo日志序列號
Added dirty pages up to已添加到臟頁列表的頁面的lsn值
Pages flushed up to已經刷新到磁盤臟頁的lsn值
Last checkpoint at當前checkpoit_lsn的值
Log minimum file id isredo日志文件的最小文件ID
Log maximum file id isredo日志文件的最大文件ID

【12】innodb_flush_log_at_trx_commit

redo日志刷新到磁盤的方式由innodb_flush_log_at_trx_commit控制,刷新方式有3種,分別為:

innodb_flush_log_at_trx_commit值刷新方式
0事務提交時不立即刷新redo日志到磁盤,由后臺線程去刷新到磁盤,如果服務器掛了,后臺線程沒及時將redo日志刷新到磁盤,事務對該頁面的修改就會丟失
1事務提交時就將redo日志同步到磁盤
2事務提交時將redo日志寫入log buffer,不需要刷新到磁盤,當數據庫掛,操作系統掛也能保證持久性,數據庫和操作系統都掛就保證不了持久性了

【13】崩壞是redo日志恢復

redo日志的恢復過程如下:

1、確定恢復的起點,也就是checkpoint_lsn,

2、確定恢復的終點,也就是ib_logfile中block未寫滿的位置,

3、從checkpoint_lsn恢復頁時,如果頁的FIL_PAGE_LSN值,也就是newest_modification的值如果大于checkpoint_lsn,說明該頁已經恢復,直接跳過,如果小于checkpoint_lsn,就需要讀取redo日志進行恢復。

3、總結

redo日志是InnoDB使用崩潰恢復的核心機制,通過物理日志、順序寫入和checkpoint機制,保證事務的持久性并且提高了數據庫的性能。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • 解壓版MYSQL中文亂碼問題解決方案

    解壓版MYSQL中文亂碼問題解決方案

    這篇文章主要介紹了解壓版MYSQL中文亂碼問題解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • 使用mss2sql工具將SqlServer轉換為Mysql全記錄

    使用mss2sql工具將SqlServer轉換為Mysql全記錄

    上篇文章我們講訴了在mssql數據轉換成mysql數據中,用Navicat Premium導入數據很完美,但是創(chuàng)建表的時候數據類型轉換不是很完美,本文我們來講訴下用mss2sql工具來創(chuàng)建表,順便說下導入數據
    2014-08-08
  • mysql數據庫表的多條件查詢語句

    mysql數據庫表的多條件查詢語句

    這篇文章主要介紹了mysql數據庫表的多條件查詢語句,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-06-06
  • 詳解MySQL中SlowLog的配置方法(圖文)

    詳解MySQL中SlowLog的配置方法(圖文)

    mysql 日志系統上線有段時間了,前端在慢慢切站點過來寫入,未雨綢繆 diy了套 mysql 監(jiān)控工具
    2014-02-02
  • MySQL?8.0.28?安裝配置圖文教程

    MySQL?8.0.28?安裝配置圖文教程

    這篇文章主要為大家詳細介紹了MySQL?8.0.28?安裝配置圖文教程,文中安裝步驟介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • MySQL 觸發(fā)器的使用及需要注意的地方

    MySQL 觸發(fā)器的使用及需要注意的地方

    這篇文章主要介紹了MySQL 觸發(fā)器的使用及需要注意的地方,幫助大家更好的理解和使用MySQL,感興趣的朋友可以了解下
    2021-01-01
  • CentOS下重啟Mysql的各種方法(推薦)

    CentOS下重啟Mysql的各種方法(推薦)

    這篇文章主要介紹了CentOS下重啟Mysql的各種方法(推薦),非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-01-01
  • MySQL 導出數據為csv格式的方法

    MySQL 導出數據為csv格式的方法

    這篇文章主要介紹了MySQL 導出數據為csv格式的方法,需要的朋友可以參考下
    2015-10-10
  • 解決找回mysql數據庫密碼和密碼過期問題

    解決找回mysql數據庫密碼和密碼過期問題

    這篇文章主要介紹了解決找回mysql數據庫密碼和密碼過期問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • 詳細講解安全升級MySQL的方法

    詳細講解安全升級MySQL的方法

    這篇文章主要介紹了詳細講解安全升級MySQL的方法,在此特別推薦使用Percona Toolkit來輔助升級,當然,本文示例基于Linux環(huán)境,需要的朋友可以參考下
    2015-06-06

最新評論