【MYSQL】innodb兩次寫(double write)實現解析

ai3707發表於2016-04-22
   在innodb儲存引擎中,有一個叫doublewrite技術模組,是可選的。它透過引數InnoDB_doublewrite的值來控制,如果為0表示不啟用,可以透過show status like  "%InnoDB_dblwr%"來檢視,doublewrite技術帶給innodb儲存引擎的是資料頁的可靠性,下面對doublewrite技術進行解析,讓大家充分理解doublewrite是如何做到保障資料頁的可靠性。

一、doublewrite應用場景:
    我們知道,innodb的資料頁一般大小是16KB,MySQL存取資料的最小單位也是頁,而作業系統並不能保障一個資料頁的原子性,也就是說當寫入資料時,有可能在一個頁中寫入一半時(比如8K)資料庫當機,這種情況稱為部分寫失效(partial page write),從而導致資料丟失。
      大家也許會問,難道我不可以根據redo log進行資料恢復嗎?答案是肯定的也是否定的,要分為兩種情況:1、資料庫當機,物理檔案完好無損,是可以透過redo log進行崩潰恢復。2、資料庫當機,正在重新整理到磁碟的頁發生partial page write,而正好在磁碟上的這個資料頁由於當機發生損壞,這時就無法透過redo log進行資料恢復了,為什麼?我們必須要清楚的認識到,redo log裡記錄的是對頁的物理操作!比如一條redo記錄"page number  xx,偏移量 800  寫記錄 “this is abc”",那當頁損壞時,這條redo記錄還有意義嗎?於是在這種特殊情況下,doublewrite就派上用場啦!

二、doublewrite體系結構及工作流程
    doublewrite由兩部分組成,一部分為記憶體中的doublewrite buffer,其大小為2MB,另一部分是磁碟上共享表空間(ibdata x)中連續的128個頁,即2個區(extent),大小也是2M。doublewrite工作流程如下:
        1、當一系列機制(main函式觸發、checkpoint等)觸發資料緩衝池中的髒頁進行重新整理時,並不直接寫磁碟,而是會透過memcpy函式將髒頁先複製到記憶體中的doublewrite buffer,之後透過doublewrite buffer再分兩次、每次1MB順序寫入共享表空間的物理磁碟上。
        2、馬上呼叫fsync函式,同步髒頁進磁碟
      由於在這個過程中,doublewrite頁的儲存時連續的,因此寫入磁碟為順序寫,效能很高;完成doublewrite後,再將髒頁寫入實際的各個表空間檔案,這時寫入就是離散的了。各模組協作情況如下圖(第一步應為髒頁產生的redo記錄logbuffer,然後logbuffer寫入redo log file,為簡化次要步驟直接連線表示):
              
    檢視doublewrite工作情況,可以執行命令:
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)
    以上資料顯示,doublewrite一共寫了 61932183個頁,一共寫了15237891次,從這組資料我們可以分析,之前講過在開啟doublewrite後,每次髒頁重新整理必須要先寫doublewrite,而doublewrite存在於磁碟上的是兩個連續的區,每個區由連續的頁組成,一般情況下一個區最多有64個頁,所以一次IO寫入應該可以最多寫64個頁。而根據以上我這個系統Innodb_dblwr_pages_written與Innodb_dblwr_writes的比例來看,大概在4左右,遠遠還沒到64,所以從這個角度也可以看出,系統寫入壓力並不高。

三、崩潰恢復    
    如果作業系統在將頁寫入磁碟的過程中發生崩潰,如上圖,在恢復過程中,innodb儲存引擎可以從共享表空間的doublewrite中找到該頁的一個最近的副本,將其複製到表空間檔案,再應用redo log,就完成了恢復過程。因為有副本所以也不擔心表空間中資料頁是否損壞。

四、建議
    innodb儲存引擎引入double write技術後,引數skip_innodb_doublewrite雖然可以禁止使用doublewrite功能,但還是強烈建議大家使用doublewrite。避免部分寫失效問題,當然,有些檔案系統本身就提供了部分寫失效防範機制,如ZFS檔案系統,在這種情況下,就可以不開啟doublewrite了


        

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

相關文章