深入解析MySQL雙寫緩沖區(qū)
在數(shù)據(jù)庫(kù)系統(tǒng)的世界中,保障數(shù)據(jù)的完整性和穩(wěn)定性是至關(guān)重要的任務(wù)。為了實(shí)現(xiàn)這一目標(biāo),MySQL內(nèi)部使用了許多精巧而高效的機(jī)制。
InnoDB是MySQL中一種常用的事務(wù)性存儲(chǔ)引擎,它具有很多優(yōu)秀的特性。其中,Doublewrite Buffer是InnoDB的一個(gè)重要特性之一,本文將介紹Doublewrite Buffer的原理和應(yīng)用,幫助讀者深入理解其如何提高M(jìn)ySQL的數(shù)據(jù)可靠性并防止可能的數(shù)據(jù)損壞。
為什么需要Doublewrite Buffer
我們常見的服務(wù)器一般都是Linux操作系統(tǒng),Linux文件系統(tǒng)頁(yè)(OS Page)的大小默認(rèn)是4KB。而MySQL的頁(yè)(Page)大小默認(rèn)是16KB。
可以使用如下命令查看MySQL的Page大?。?/p>
SHOW VARIABLES LIKE 'innodb_page_size';
一般情況下,其余程序因?yàn)樾枰僮飨到y(tǒng)交互,所以它們的頁(yè)(Page)大小都為操作系統(tǒng)頁(yè)大小的整數(shù)倍。比如,Oracle的Page大小為8KB。
MySQL程序是跑在Linux操作系統(tǒng)上的,理所當(dāng)然要跟操作系統(tǒng)交互,所以MySQL中一頁(yè)數(shù)據(jù)刷到磁盤,要寫4個(gè)文件系統(tǒng)里的頁(yè)。
如圖所示:
需要注意的是,這個(gè)刷頁(yè)的操作并非原子操作,比如我操作系統(tǒng)寫到第二個(gè)頁(yè)的時(shí)候,Linux機(jī)器斷電了,這時(shí)候就會(huì)出現(xiàn)問題了。造成「頁(yè)數(shù)據(jù)損壞」。并且這種頁(yè)數(shù)據(jù)損壞靠 redo日志是無(wú)法修復(fù)的。
redo重做日志中記錄的是對(duì)頁(yè)的物理操作,而不是頁(yè)面的全量記錄,當(dāng)發(fā)生「Partial Page Write(部分頁(yè)寫入)」問題時(shí),出現(xiàn)問題的是未修改過的數(shù)據(jù),此時(shí)redo日志無(wú)能為力。
Doublewrite Buffer的出現(xiàn)就是為了解決上面的這種情況,給InnoDB存儲(chǔ)引擎提供了數(shù)據(jù)頁(yè)的可靠性,雖然名字帶了Buffer,但實(shí)際上Doublewrite Buffer是「內(nèi)存+磁盤」的結(jié)構(gòu)。
內(nèi)存結(jié)構(gòu):Doublewrite Buffer內(nèi)存結(jié)構(gòu)由128個(gè)頁(yè)(Page)構(gòu)成,大小是2MB。
磁盤結(jié)構(gòu):Doublewrite Buffer磁盤結(jié)構(gòu)在系統(tǒng)表空間上是128個(gè)頁(yè)(2個(gè)區(qū),extend1和extend2),大小是2MB。
Doublewrite Buffer的原理是,再把數(shù)據(jù)頁(yè)寫到數(shù)據(jù)文件之前,InnoDB先把它們寫到一個(gè)叫「doublewrite buffer(雙寫緩沖區(qū))」的共享表空間內(nèi),在寫doublewrite buffer完成后,InnoDB才會(huì)把頁(yè)寫到數(shù)據(jù)文件適當(dāng)?shù)奈恢谩?/p>
如果在寫頁(yè)的過程中發(fā)生意外崩潰,InnoDB會(huì)在doublewrite buffer中找到完好的page副本用于恢復(fù)。
Doublewrite Buffer原理
如上圖所示,當(dāng)有數(shù)據(jù)頁(yè)要刷盤時(shí):
頁(yè)數(shù)據(jù)先通過
memcpy
函數(shù)拷貝至內(nèi)存中的Doublewrite Buffer中。Doublewrite Buffer的內(nèi)存里的數(shù)據(jù)頁(yè),會(huì)
fsync
刷到Doublewrite Buffer的磁盤上,分兩次寫入磁盤共享表空間中(連續(xù)存儲(chǔ),順序?qū)懀阅芎芨?,每次寫1MB。Doublewrite Buffer的內(nèi)存里的數(shù)據(jù)頁(yè),再刷到數(shù)據(jù)磁盤存儲(chǔ).ibd文件上(離散寫)。
如果操作系統(tǒng)在將頁(yè)寫入磁盤的過程中發(fā)生了崩潰,在恢復(fù)過程中,InnoDB存儲(chǔ)引擎可以從共享表空間中的Double write中找到該頁(yè)的一個(gè)副本,將其復(fù)制到表空間文件,再應(yīng)用redo日志。
所以在正常的情況下,MySQL寫數(shù)據(jù)頁(yè)時(shí),會(huì)寫兩遍到磁盤上,第一遍是寫到doublewrite buffer,第二遍是寫到真正的數(shù)據(jù)文件中,這便是「Doublewrite」的由來(lái)。
我們可以通過如下命令來(lái)監(jiān)控Doublewrite Buffer工作負(fù)載,該命令用于顯示有關(guān)雙寫緩沖區(qū)(doublewrite buffer)的統(tǒng)計(jì)信息。‘%dblwr%’ 是一個(gè)通配符,匹配所有包含 ‘dblwr’ 的狀態(tài)變量。
show global status like '%dblwr%';
這個(gè)命令可能會(huì)產(chǎn)生如下格式的輸出:
+------------------------+-------+ | Variable_name | Value | +------------------------+-------+ | Innodb_dblwr_writes | 1000 | | Innodb_dblwr_pages_written | 8000 | +------------------------+-------+
Doublewrite Buffer和redo log
在MySQL的InnoDB存儲(chǔ)引擎中,Redo log和Doublewrite Buffer共同工作以確保數(shù)據(jù)的持久性和恢復(fù)能力。
- 當(dāng)有一個(gè)DML(如INSERT、UPDATE)操作發(fā)生時(shí), InnoDB會(huì)首先將這個(gè)操作寫入redo log(內(nèi)存)。這些日志被稱為未檢查點(diǎn)(uncheckpointed)的redo日志。
- 然后,在修改內(nèi)存中相應(yīng)的數(shù)據(jù)頁(yè)之前,需要將這些更改記錄在磁盤上。但是直接把這些修改的頁(yè)寫到其真正的位置可能會(huì)因發(fā)生故障導(dǎo)致頁(yè)部分更新,從而導(dǎo)致數(shù)據(jù)不一致。因此,InnoDB的做法是先將這些修改的頁(yè)按順序?qū)懭雂oublewrite buffer。這就是為什么叫做 “doublewrite” —— 數(shù)據(jù)實(shí)際上被寫了兩次,先在doublewrite buffer,然后在它們真正的位置。
- 一旦這些頁(yè)被安全地寫入doublewrite buffer,它們就可以按原始的順序?qū)懟氐轿募到y(tǒng)中。即使這個(gè)過程在寫回?cái)?shù)據(jù)時(shí)發(fā)生故障,我們?nèi)匀豢梢詮膁oublewrite buffer中恢復(fù)數(shù)據(jù)。
- 最后,當(dāng)事務(wù)提交時(shí),相關(guān)聯(lián)的redo log會(huì)被寫入磁盤。這樣即使系統(tǒng)崩潰,redo log也可以用來(lái)重播(replay)事務(wù)并恢復(fù)數(shù)據(jù)庫(kù)。
在系統(tǒng)恢復(fù)期間,InnoDB會(huì)檢查doublewrite buffer,并嘗試從中恢復(fù)損壞的數(shù)據(jù)頁(yè)。如果doublewrite buffer中的數(shù)據(jù)是完整的,那么InnoDB就會(huì)用doublewrite buffer中的數(shù)據(jù)來(lái)更新?lián)p壞的頁(yè)。否則,如果doublewrite buffer中的數(shù)據(jù)不完整,InnoDB也有可能丟棄buffer內(nèi)容,重新執(zhí)行那條redo log以嘗試恢復(fù)數(shù)據(jù)。
所以,Redo log和Doublewrite Buffer的協(xié)作可以確保數(shù)據(jù)的完整性和持久性。如果在寫入過程中發(fā)生故障,我們可以從doublewrite buffer中恢復(fù)數(shù)據(jù),并通過redo log來(lái)進(jìn)行事務(wù)的重播。
Doublewrite Buffer相關(guān)參數(shù)
以下是一些與Doublewrite Buffer相關(guān)的參數(shù)及其含義:
innodb_doublewrite
: 這個(gè)參數(shù)用于啟用或禁用雙寫緩沖區(qū)。設(shè)置為1時(shí)啟用,設(shè)置為0時(shí)禁用, 默認(rèn)值為1。innodb_doublewrite_files
: 這個(gè)參數(shù)定義了多少個(gè)雙寫文件被使用。默認(rèn)值為2,有效范圍從2到127。innodb_doublewrite_dir
: 這個(gè)參數(shù)指定了存儲(chǔ)雙寫緩沖文件的目錄的路徑。默認(rèn)為空字符串,表示將文件存儲(chǔ)在數(shù)據(jù)目錄中。innodb_doublewrite_batch_size
: 這個(gè)參數(shù)定義了每次批處理操作寫入的字節(jié)數(shù)。默認(rèn)值為0,表示InnoDB會(huì)選擇最佳的批量大小。innodb_doublewrite_pages
:這個(gè)參數(shù)定義了每個(gè)雙寫文件包含多少頁(yè)面。默認(rèn)值為128。
總結(jié)
Doublewrite Buffer是InnoDB的一個(gè)重要特性,用于保證MySQL數(shù)據(jù)的可靠性和一致性。
它的實(shí)現(xiàn)原理是通過將要寫入磁盤的數(shù)據(jù)先寫入到Doublewrite Buffer中的內(nèi)存緩存區(qū)域,然后再寫入到磁盤的兩個(gè)不同位置,來(lái)避免由于磁盤損壞等因素導(dǎo)致數(shù)據(jù)丟失或不一致的問題。
總的來(lái)說(shuō),Doublewrite Buffer對(duì)于改善數(shù)據(jù)庫(kù)性能和數(shù)據(jù)完整性起著至關(guān)重要的作用。盡管其引入了一些開銷,但在大多數(shù)情況下,這些成本都被其提供的安全性和可靠性所抵消。
到此這篇關(guān)于深入解析MySQL雙寫緩沖區(qū)的文章就介紹到這了,更多相關(guān)MySQL雙寫緩沖區(qū)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL server has gone away錯(cuò)誤提示解決方法
今天遇到類似的情景,MySQL只是冷冷的說(shuō):MySQL server has gone away。2008-11-11Mysql遷移Postgresql的實(shí)現(xiàn)示例
本文主要介紹了Mysql遷移Postgresql的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03MySQL不使用order by實(shí)現(xiàn)排名的三種思路總結(jié)
ORDER BY語(yǔ)句用于根據(jù)指定的列對(duì)結(jié)果集進(jìn)行排序,在日常開發(fā)中也經(jīng)常會(huì)用到,但下面這篇文章主要給大家介紹了關(guān)于MySQL不使用order by實(shí)現(xiàn)排名的三種思路,需要的朋友可以參考下2021-06-06MySQL架構(gòu)體系知識(shí)點(diǎn)總結(jié)
在本篇內(nèi)容里我們給大家整理了關(guān)于MySQL架構(gòu)體系的相關(guān)知識(shí)點(diǎn)內(nèi)容以及相關(guān)實(shí)例,需要的朋友們學(xué)習(xí)下。2019-02-02關(guān)于mysql innodb count(*)速度慢的解決辦法
innodb引擎在統(tǒng)計(jì)方面和myisam是不同的,Myisam內(nèi)置了一個(gè)計(jì)數(shù)器,所以在使用 select count(*) from table 的時(shí)候,直接可以從計(jì)數(shù)器中取出數(shù)據(jù)。而innodb必須全表掃描一次方能得到總的數(shù)量2012-12-12mysql8關(guān)閉binlog并清空Binlog的方法
這篇文章主要介紹了mysql8關(guān)閉binlog并清空Binlog,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09mysql中的delete,drop和truncate有什么區(qū)別
這篇文章主要介紹了mysql中的delete,drop和truncate有什么區(qū)別,三者的用法和使用場(chǎng)景又完全不同,接下來(lái)我們來(lái)看看具體的區(qū)別吧,希望對(duì)你的學(xué)習(xí)有所幫助2022-06-06