InnoDB關鍵特性之double write


臟頁刷盤的風險

兩次寫的原理機制

  1、解決問題

  2、使用場景

  3、doublewrite的工作流程

  4、崩潰恢復

# doublewrite的副作用

  1、監控doublewrite負載

  2、關閉doublewrite場景

一、臟頁刷盤風險

關於IO的最小單位:

  1、數據庫IO的最小單位是16K(MySQL默認,oracle是8K)

  2、文件系統IO的最小單位是4K(也有1K的)

  3、磁盤IO的最小單位是512字節

因此,存在IO寫入導致page損壞的風險:

  

 

二、doublewrite:兩次寫

  提高innodb的可靠性,用來解決部分寫失敗(partial page write頁斷裂)。

1、Double write解決了什么問題

  一個數據頁的大小是16K,假設在把內存中的臟頁寫到數據庫的時候,寫了2K突然掉電,也就是說前2K數據是新的,后14K是舊的,那么磁盤數據庫這個數據頁就是不完整的,是一個壞掉的數據頁。redo只能加上舊、校檢完整的數據頁恢復一個臟塊,不能修復壞掉的數據頁,所以這個數據就丟失了,可能會造成數據不一致,所以需要double write。

2、使用情景

  當數據庫正在從內存想磁盤寫一個數據頁是,數據庫宕機,從而導致這個頁只寫了部分數據,這就是部分寫失效,它會導致數據丟失。這時是無法通過重做日志恢復的,因為重做日志記錄的是對頁的物理修改,如果頁本身已經損壞,重做日志也無能為力。

3、double write工作流程

 

  doublewrite由兩部分組成,一部分為內存中的doublewrite buffer,其大小為2MB,另一部分是磁盤上共享表空間(ibdata x)中連續的128個頁,即2個區(extent),大小也是2M。

  1、當一系列機制觸發數據緩沖池中的臟頁刷新時,並不直接寫入磁盤數據文件中,而是先拷貝至內存中的doublewrite buffer中;

  2、接着從兩次寫緩沖區分兩次寫入磁盤共享表空間中(連續存儲,順序寫,性能很高),每次寫1MB;

  3、待第二步完成后,再將doublewrite buffer中的臟頁數據寫入實際的各個表空間文件(離散寫);(臟頁數據固化后,即進行標記對應doublewrite數據可覆蓋)

4、doublewrite的崩潰恢復

  如果操作系統在將頁寫入磁盤的過程中發生崩潰,在恢復過程中,innodb存儲引擎可以從共享表空間的doublewrite中找到該頁的一個最近的副本,將其復制到表空間文件,再應用redo log,就完成了恢復過程。

  因為有副本所以也不擔心表空間中數據頁是否損壞。

Q:為什么log write不需要doublewrite的支持?

A:

  因為redolog寫入的單位就是512字節,也就是磁盤IO的最小單位,所以無所謂數據損壞。

 

三、doublewrite的副作用

1、double write帶來的寫負載

  1、double write是一個buffer, 但其實它是開在物理文件上的一個buffer, 其實也就是file, 所以它會導致系統有更多的fsync操作, 而硬盤的fsync性能是很慢的, 所以它會降低mysql的整體性能。

  2、但是,doublewrite buffer寫入磁盤共享表空間這個過程是連續存儲,是順序寫,性能非常高,(約占寫的%10),犧牲一點寫性能來保證數據頁的完整還是很有必要的。

2、監控double write工作負載

mysql> show global status like '%dblwr%'; +----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Innodb_dblwr_pages_written | 7     |
| Innodb_dblwr_writes        | 3     |
+----------------------------+-------+
2 rows in set (0.00 sec)

  關注點:Innodb_dblwr_pages_written / Innodb_dblwr_writes

  開啟doublewrite后,每次臟頁刷新必須要先寫doublewrite,而doublewrite存在於磁盤上的是兩個連續的區,每個區由連續的頁組成,一般情況下一個區最多有64個頁,所以一次IO寫入應該可以最多寫64個頁。

  而根據以上系統Innodb_dblwr_pages_written與Innodb_dblwr_writes的比例來看,大概在3左右,遠遠還沒到64(如果約等於64,那么說明系統的寫壓力非常大,有大量的臟頁要往磁盤上寫),所以從這個角度也可以看出,系統寫入壓力並不高。

3、關閉double write適合的場景

  1、海量DML

  2、不懼怕數據損壞和丟失

  3、系統寫負載成為主要負載

mysql> show variables like '%double%'; +--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| innodb_doublewrite | ON    |
+--------------------+-------+
1 row in set (0.04 sec)

  作為InnoDB的一個關鍵特性,doublewrite功能默認是開啟的,但是在上述特殊的一些場景也可以視情況關閉,來提高數據庫寫性能。靜態參數,配置文件修改,重啟數據庫。

4、為什么沒有把double write里面的數據寫到data page里面呢?

  1、double write里面的數據是連續的,如果直接寫到data page里面,而data page的頁又是離散的,寫入會很慢。

  2、double write里面的數據沒有辦法被及時的覆蓋掉,導致double write的壓力很大;短時間內可能會出現double write溢出的情況。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM