# 臟頁刷盤的風險
1、解決問題
2、使用場景
4、崩潰恢復
# doublewrite的副作用
關於IO的最小單位:
1、數據庫IO的最小單位是16K(MySQL默認,oracle是8K)
2、文件系統IO的最小單位是4K(也有1K的)
3、磁盤IO的最小單位是512字節
因此,存在IO寫入導致page損壞的風險:
提高innodb的可靠性,用來解決部分寫失敗(partial page write頁斷裂)。
1、Double write解決了什么問題
一個數據頁的大小是16K,假設在把內存中的臟頁寫到數據庫的時候,寫了2K突然掉電,也就是說前2K數據是新的,后14K是舊的,那么磁盤數據庫這個數據頁就是不完整的,是一個壞掉的數據頁。redo只能加上舊、校檢完整的數據頁恢復一個臟塊,不能修復壞掉的數據頁,所以這個數據就丟失了,可能會造成數據不一致,所以需要double write。
2、使用情景
當數據庫正在從內存想磁盤寫一個數據頁是,數據庫宕機,從而導致這個頁只寫了部分數據,這就是部分寫失效,它會導致數據丟失。這時是無法通過重做日志恢復的,因為重做日志記錄的是對頁的物理修改,如果頁本身已經損壞,重做日志也無能為力。
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),犧牲一點寫性能來保證數據頁的完整還是很有必要的。
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,那么說明系統的寫壓力非常大,有大量的臟頁要往磁盤上寫),所以從這個角度也可以看出,系統寫入壓力並不高。
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溢出的情況。