InnoDB關鍵特性之double write
一、髒頁刷盤風險
關於IO的最小單位:
1、資料庫IO的最小單位是16K(MySQL預設,oracle是8K)
2、檔案系統IO的最小單位是4K(也有1K的)
3、磁碟IO的最小單位是512K
因此,存在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溢位的情況。