溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

【MYSQL】innodb兩次寫(xiě)(double write)實(shí)現(xiàn)解析

發(fā)布時(shí)間:2020-08-11 13:56:05 來(lái)源:ITPUB博客 閱讀:419 作者:ai3707 欄目:MySQL數(shù)據(jù)庫(kù)
   在innodb存儲(chǔ)引擎中,有一個(gè)叫doublewrite技術(shù)模塊,是可選的。它通過(guò)參數(shù)InnoDB_doublewrite的值來(lái)控制,如果為0表示不啟用,可以通過(guò)show status like  "%InnoDB_dblwr%"來(lái)查看,doublewrite技術(shù)帶給innodb存儲(chǔ)引擎的是數(shù)據(jù)頁(yè)的可靠性,下面對(duì)doublewrite技術(shù)進(jìn)行解析,讓大家充分理解doublewrite是如何做到保障數(shù)據(jù)頁(yè)的可靠性。

一、doublewrite應(yīng)用場(chǎng)景:
    我們知道,innodb的數(shù)據(jù)頁(yè)一般大小是16KB,MySQL存取數(shù)據(jù)的最小單位也是頁(yè),而操作系統(tǒng)并不能保障一個(gè)數(shù)據(jù)頁(yè)的原子性,也就是說(shuō)當(dāng)寫(xiě)入數(shù)據(jù)時(shí),有可能在一個(gè)頁(yè)中寫(xiě)入一半時(shí)(比如8K)數(shù)據(jù)庫(kù)宕機(jī),這種情況稱為部分寫(xiě)失效(partial page write),從而導(dǎo)致數(shù)據(jù)丟失。
      大家也許會(huì)問(wèn),難道我不可以根據(jù)redo log進(jìn)行數(shù)據(jù)恢復(fù)嗎?答案是肯定的也是否定的,要分為兩種情況:1、數(shù)據(jù)庫(kù)宕機(jī),物理文件完好無(wú)損,是可以通過(guò)redo log進(jìn)行崩潰恢復(fù)。2、數(shù)據(jù)庫(kù)宕機(jī),正在刷新到磁盤(pán)的頁(yè)發(fā)生partial page write,而正好在磁盤(pán)上的這個(gè)數(shù)據(jù)頁(yè)由于宕機(jī)發(fā)生損壞,這時(shí)就無(wú)法通過(guò)redo log進(jìn)行數(shù)據(jù)恢復(fù)了,為什么?我們必須要清楚的認(rèn)識(shí)到,redo log里記錄的是對(duì)頁(yè)的物理操作!比如一條redo記錄"page number  xx,偏移量 800  寫(xiě)記錄 “this is abc”",那當(dāng)頁(yè)損壞時(shí),這條redo記錄還有意義嗎?于是在這種特殊情況下,doublewrite就派上用場(chǎng)啦!

二、doublewrite體系結(jié)構(gòu)及工作流程
    doublewrite由兩部分組成,一部分為內(nèi)存中的doublewrite buffer,其大小為2MB,另一部分是磁盤(pán)上共享表空間(ibdata x)中連續(xù)的128個(gè)頁(yè),即2個(gè)區(qū)(extent),大小也是2M。doublewrite工作流程如下:
        1、當(dāng)一系列機(jī)制(main函數(shù)觸發(fā)、checkpoint等)觸發(fā)數(shù)據(jù)緩沖池中的臟頁(yè)進(jìn)行刷新時(shí),并不直接寫(xiě)磁盤(pán),而是會(huì)通過(guò)memcpy函數(shù)將臟頁(yè)先復(fù)制到內(nèi)存中的doublewrite buffer,之后通過(guò)doublewrite buffer再分兩次、每次1MB順序?qū)懭牍蚕肀砜臻g的物理磁盤(pán)上。
        2、馬上調(diào)用fsync函數(shù),同步臟頁(yè)進(jìn)磁盤(pán)
      由于在這個(gè)過(guò)程中,doublewrite頁(yè)的存儲(chǔ)時(shí)連續(xù)的,因此寫(xiě)入磁盤(pán)為順序?qū)?,性能很高;完成doublewrite后,再將臟頁(yè)寫(xiě)入實(shí)際的各個(gè)表空間文件,這時(shí)寫(xiě)入就是離散的了。各模塊協(xié)作情況如下圖(第一步應(yīng)為臟頁(yè)產(chǎn)生的redo記錄logbuffer,然后logbuffer寫(xiě)入redo log file,為簡(jiǎn)化次要步驟直接連線表示):
              【MYSQL】innodb兩次寫(xiě)(double write)實(shí)現(xiàn)解析
    查看doublewrite工作情況,可以執(zhí)行命令:
mysql> show global status like 'innodb_dblwr%'\G
*************************** 1. row ***************************
Variable_name: Innodb_dblwr_pages_written
        Value: 61932183
*************************** 2. row ***************************
Variable_name: Innodb_dblwr_writes
        Value: 15237891
2 rows in set (0.00 sec)
    以上數(shù)據(jù)顯示,doublewrite一共寫(xiě)了 61932183個(gè)頁(yè),一共寫(xiě)了15237891次,從這組數(shù)據(jù)我們可以分析,之前講過(guò)在開(kāi)啟doublewrite后,每次臟頁(yè)刷新必須要先寫(xiě)doublewrite,而doublewrite存在于磁盤(pán)上的是兩個(gè)連續(xù)的區(qū),每個(gè)區(qū)由連續(xù)的頁(yè)組成,一般情況下一個(gè)區(qū)最多有64個(gè)頁(yè),所以一次IO寫(xiě)入應(yīng)該可以最多寫(xiě)64個(gè)頁(yè)。而根據(jù)以上我這個(gè)系統(tǒng)Innodb_dblwr_pages_written與Innodb_dblwr_writes的比例來(lái)看,大概在4左右,遠(yuǎn)遠(yuǎn)還沒(méi)到64,所以從這個(gè)角度也可以看出,系統(tǒng)寫(xiě)入壓力并不高。

三、崩潰恢復(fù)    
    如果操作系統(tǒng)在將頁(yè)寫(xiě)入磁盤(pán)的過(guò)程中發(fā)生崩潰,如上圖,在恢復(fù)過(guò)程中,innodb存儲(chǔ)引擎可以從共享表空間的doublewrite中找到該頁(yè)的一個(gè)最近的副本,將其復(fù)制到表空間文件,再應(yīng)用redo log,就完成了恢復(fù)過(guò)程。因?yàn)橛懈北舅砸膊粨?dān)心表空間中數(shù)據(jù)頁(yè)是否損壞。

四、建議
    innodb存儲(chǔ)引擎引入double write技術(shù)后,參數(shù)skip_innodb_doublewrite雖然可以禁止使用doublewrite功能,但還是強(qiáng)烈建議大家使用doublewrite。避免部分寫(xiě)失效問(wèn)題,當(dāng)然,有些文件系統(tǒng)本身就提供了部分寫(xiě)失效防范機(jī)制,如ZFS文件系統(tǒng),在這種情況下,就可以不開(kāi)啟doublewrite了


        
向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI