自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深入解析 MySQL 雙寫(xiě)緩沖區(qū)

數(shù)據(jù)庫(kù) MySQL
本文將介紹Doublewrite Buffer的原理和應(yīng)用,幫助讀者深入理解其如何提高M(jìn)ySQL的數(shù)據(jù)可靠性并防止可能的數(shù)據(jù)損壞。

在數(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

我們常見(jiàn)的服務(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ù)刷到磁盤(pán),要寫(xiě)4個(gè)文件系統(tǒng)里的頁(yè)。

如圖所示:

需要注意的是,這個(gè)刷頁(yè)的操作并非原子操作,比如我操作系統(tǒng)寫(xiě)到第二個(gè)頁(yè)的時(shí)候,Linux機(jī)器斷電了,這時(shí)候就會(huì)出現(xiàn)問(wèn)題了。造成「頁(yè)數(shù)據(jù)損壞」。并且這種頁(yè)數(shù)據(jù)損壞靠 redo日志是無(wú)法修復(fù)的。

redo重做日志中記錄的是對(duì)頁(yè)的物理操作,而不是頁(yè)面的全量記錄,當(dāng)發(fā)生「Partial Page Write(部分頁(yè)寫(xiě)入)」問(wèn)題時(shí),出現(xiàn)問(wèn)題的是未修改過(guò)的數(shù)據(jù),此時(shí)redo日志無(wú)能為力。

Doublewrite Buffer的出現(xiàn)就是為了解決上面的這種情況,給InnoDB存儲(chǔ)引擎提供了數(shù)據(jù)頁(yè)的可靠性,雖然名字帶了Buffer,但實(shí)際上Doublewrite Buffer是「內(nèi)存+磁盤(pán)」的結(jié)構(gòu)。

  • 內(nèi)存結(jié)構(gòu):Doublewrite Buffer內(nèi)存結(jié)構(gòu)由128個(gè)頁(yè)(Page)構(gòu)成,大小是2MB。
  • 磁盤(pán)結(jié)構(gòu):Doublewrite Buffer磁盤(pán)結(jié)構(gòu)在系統(tǒng)表空間上是128個(gè)頁(yè)(2個(gè)區(qū),extend1和extend2),大小是2MB。

Doublewrite Buffer的原理是,再把數(shù)據(jù)頁(yè)寫(xiě)到數(shù)據(jù)文件之前,InnoDB先把它們寫(xiě)到一個(gè)叫「doublewrite buffer(雙寫(xiě)緩沖區(qū))」的共享表空間內(nèi),在寫(xiě)doublewrite buffer完成后,InnoDB才會(huì)把頁(yè)寫(xiě)到數(shù)據(jù)文件適當(dāng)?shù)奈恢谩?/p>

如果在寫(xiě)頁(yè)的過(guò)程中發(fā)生意外崩潰,InnoDB會(huì)在doublewrite buffer中找到完好的page副本用于恢復(fù)。

Doublewrite Buffer原理

如上圖所示,當(dāng)有數(shù)據(jù)頁(yè)要刷盤(pán)時(shí):

  • 頁(yè)數(shù)據(jù)先通過(guò)memcpy函數(shù)拷貝至內(nèi)存中的Doublewrite Buffer中。
  • Doublewrite Buffer的內(nèi)存里的數(shù)據(jù)頁(yè),會(huì)fsync刷到Doublewrite Buffer的磁盤(pán)上,分兩次寫(xiě)入磁盤(pán)共享表空間中(連續(xù)存儲(chǔ),順序?qū)懀阅芎芨?,每次寫(xiě)1MB。
  • Doublewrite Buffer的內(nèi)存里的數(shù)據(jù)頁(yè),再刷到數(shù)據(jù)磁盤(pán)存儲(chǔ).ibd文件上(離散寫(xiě))。

如果操作系統(tǒng)在將頁(yè)寫(xiě)入磁盤(pán)的過(guò)程中發(fā)生了崩潰,在恢復(fù)過(guò)程中,InnoDB存儲(chǔ)引擎可以從共享表空間中的Double write中找到該頁(yè)的一個(gè)副本,將其復(fù)制到表空間文件,再應(yīng)用redo日志。

所以在正常的情況下,MySQL寫(xiě)數(shù)據(jù)頁(yè)時(shí),會(huì)寫(xiě)兩遍到磁盤(pán)上,第一遍是寫(xiě)到doublewrite buffer,第二遍是寫(xiě)到真正的數(shù)據(jù)文件中,這便是「Doublewrite」的由來(lái)。

我們可以通過(guò)如下命令來(lái)監(jiān)控Doublewrite Buffer工作負(fù)載,該命令用于顯示有關(guān)雙寫(xiě)緩沖區(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è)操作寫(xiě)入redo log(內(nèi)存)。這些日志被稱為未檢查點(diǎn)(uncheckpointed)的redo日志。
  • 然后,在修改內(nèi)存中相應(yīng)的數(shù)據(jù)頁(yè)之前,需要將這些更改記錄在磁盤(pán)上。但是直接把這些修改的頁(yè)寫(xiě)到其真正的位置可能會(huì)因發(fā)生故障導(dǎo)致頁(yè)部分更新,從而導(dǎo)致數(shù)據(jù)不一致。因此,InnoDB的做法是先將這些修改的頁(yè)按順序?qū)懭雂oublewrite buffer。這就是為什么叫做 "doublewrite" —— 數(shù)據(jù)實(shí)際上被寫(xiě)了兩次,先在doublewrite buffer,然后在它們真正的位置。
  • 一旦這些頁(yè)被安全地寫(xiě)入doublewrite buffer,它們就可以按原始的順序?qū)懟氐轿募到y(tǒng)中。即使這個(gè)過(guò)程在寫(xiě)回?cái)?shù)據(jù)時(shí)發(fā)生故障,我們?nèi)匀豢梢詮膁oublewrite buffer中恢復(fù)數(shù)據(jù)。
  • 最后,當(dāng)事務(wù)提交時(shí),相關(guān)聯(lián)的redo log會(huì)被寫(xiě)入磁盤(pán)。這樣即使系統(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ù)的完整性和持久性。如果在寫(xiě)入過(guò)程中發(fā)生故障,我們可以從doublewrite buffer中恢復(fù)數(shù)據(jù),并通過(guò)redo log來(lái)進(jìn)行事務(wù)的重播。

Doublewrite Buffer相關(guān)參數(shù)

以下是一些與Doublewrite Buffer相關(guān)的參數(shù)及其含義:

  • innodb_doublewrite:這個(gè)參數(shù)用于啟用或禁用雙寫(xiě)緩沖區(qū)。設(shè)置為1時(shí)啟用,設(shè)置為0時(shí)禁用, 默認(rèn)值為1。
  • innodb_doublewrite_files:這個(gè)參數(shù)定義了多少個(gè)雙寫(xiě)文件被使用。默認(rèn)值為2,有效范圍從2到127。
  • innodb_doublewrite_dir:這個(gè)參數(shù)指定了存儲(chǔ)雙寫(xiě)緩沖文件的目錄的路徑。默認(rèn)為空字符串,表示將文件存儲(chǔ)在數(shù)據(jù)目錄中。
  • innodb_doublewrite_batch_size: 這個(gè)參數(shù)定義了每次批處理操作寫(xiě)入的字節(jié)數(shù)。默認(rèn)值為0,表示InnoDB會(huì)選擇最佳的批量大小。
  • innodb_doublewrite_pages:這個(gè)參數(shù)定義了每個(gè)雙寫(xiě)文件包含多少頁(yè)面。默認(rèn)值為128。

總結(jié)

Doublewrite Buffer是InnoDB的一個(gè)重要特性,用于保證MySQL數(shù)據(jù)的可靠性和一致性。

它的實(shí)現(xiàn)原理是通過(guò)將要寫(xiě)入磁盤(pán)的數(shù)據(jù)先寫(xiě)入到Doublewrite Buffer中的內(nèi)存緩存區(qū)域,然后再寫(xiě)入到磁盤(pán)的兩個(gè)不同位置,來(lái)避免由于磁盤(pán)損壞等因素導(dǎo)致數(shù)據(jù)丟失或不一致的問(wèn)題。

總的來(lái)說(shuō),Doublewrite Buffer對(duì)于改善數(shù)據(jù)庫(kù)性能和數(shù)據(jù)完整性起著至關(guān)重要的作用。盡管其引入了一些開(kāi)銷,但在大多數(shù)情況下,這些成本都被其提供的安全性和可靠性所抵消。

責(zé)任編輯:趙寧寧 來(lái)源: Java隨想錄
相關(guān)推薦

2017-07-04 17:09:10

Map環(huán)形緩沖區(qū)數(shù)據(jù)

2019-02-27 13:58:29

漏洞緩沖區(qū)溢出系統(tǒng)安全

2011-03-23 12:39:44

2018-11-01 08:31:05

2017-01-09 17:03:34

2011-12-14 16:30:42

javanio

2011-03-23 11:35:00

2009-11-16 17:26:17

Oracle優(yōu)化緩沖區(qū)

2009-11-16 17:08:59

Oracle日志緩沖區(qū)

2018-01-26 14:52:43

2014-07-30 11:21:46

2009-11-16 16:59:24

Oracle優(yōu)化庫(kù)高速

2009-09-24 18:16:40

2009-07-15 15:50:48

Jython線程

2010-12-27 10:21:21

2011-07-20 10:54:14

C++

2010-09-08 15:43:18

2011-11-15 16:00:42

2022-08-09 08:31:40

C -gets函數(shù)漏洞

2022-05-07 08:27:42

緩沖區(qū)溢出堆棧
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)