# 髒頁刷盤的風險mysql
兩次寫的原理機制sql
一、解決問題數據庫
二、使用場景oracle
三、doublewrite的工做流程性能
四、崩潰恢復spa
# doublewrite的反作用操作系統
一、監控doublewrite負載3d
二、關閉doublewrite場景日誌
關於IO的最小單位:
一、數據庫IO的最小單位是16K(MySQL默認,oracle是8K)
二、文件系統IO的最小單位是4K(也有1K的)
三、磁盤IO的最小單位是512字節
所以,存在IO寫入致使page損壞的風險:
提升innodb的可靠性,用來解決部分寫失敗(partial page write頁斷裂)。
一、Double write解決了什麼問題
一個數據頁的大小是16K,假設在把內存中的髒頁寫到數據庫的時候,寫了2K忽然掉電,也就是說前2K數據是新的,後14K是舊的,那麼磁盤數據庫這個數據頁就是不完整的,是一個壞掉的數據頁。redo只能加上舊、校檢完整的數據頁恢復一個髒塊,不能修復壞掉的數據頁,因此這個數據就丟失了,可能會形成數據不一致,因此須要double write。
二、使用情景
當數據庫正在從內存想磁盤寫一個數據頁是,數據庫宕機,從而致使這個頁只寫了部分數據,這就是部分寫失效,它會致使數據丟失。這時是沒法經過重作日誌恢復的,由於重作日誌記錄的是對頁的物理修改,若是頁自己已經損壞,重作日誌也無能爲力。
doublewrite由兩部分組成,一部分爲內存中的doublewrite buffer,其大小爲2MB,另外一部分是磁盤上共享表空間(ibdata x)中連續的128個頁,即2個區(extent),大小也是2M。
一、當一系列機制觸發數據緩衝池中的髒頁刷新時,並不直接寫入磁盤數據文件中,而是先拷貝至內存中的doublewrite buffer中;
二、接着從兩次寫緩衝區分兩次寫入磁盤共享表空間中(連續存儲,順序寫,性能很高),每次寫1MB;
三、待第二步完成後,再將doublewrite buffer中的髒頁數據寫入實際的各個表空間文件(離散寫);(髒頁數據固化後,即進行標記對應doublewrite數據可覆蓋)
四、doublewrite的崩潰恢復
若是操做系統在將頁寫入磁盤的過程當中發生崩潰,在恢復過程當中,innodb存儲引擎能夠從共享表空間的doublewrite中找到該頁的一個最近的副本,將其複製到表空間文件,再應用redo log,就完成了恢復過程。
由於有副本因此也不擔憂表空間中數據頁是否損壞。
Q:爲何log write不須要doublewrite的支持?
A:
由於redolog寫入的單位就是512字節,也就是磁盤IO的最小單位,因此無所謂數據損壞。
3、doublewrite的反作用
一、double write帶來的寫負載
一、double write是一個buffer, 但其實它是開在物理文件上的一個buffer, 其實也就是file, 因此它會致使系統有更多的fsync操做, 而硬盤的fsync性能是很慢的, 因此它會下降mysql的總體性能。
二、可是,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,那麼說明系統的寫壓力很是大,有大量的髒頁要往磁盤上寫),因此從這個角度也能夠看出,系統寫入壓力並不高。
一、海量DML
二、不害怕數據損壞和丟失
三、系統寫負載成爲主要負載
mysql> show variables like '%double%'; +--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| innodb_doublewrite | ON |
+--------------------+-------+
1 row in set (0.04 sec)
做爲InnoDB的一個關鍵特性,doublewrite功能默認是開啓的,可是在上述特殊的一些場景也能夠視狀況關閉,來提升數據庫寫性能。靜態參數,配置文件修改,重啓數據庫。
四、爲何沒有把double write裏面的數據寫到data page裏面呢?
一、double write裏面的數據是連續的,若是直接寫到data page裏面,而data page的頁又是離散的,寫入會很慢。
二、double write裏面的數據沒有辦法被及時的覆蓋掉,致使double write的壓力很大;短期內可能會出現double write溢出的狀況。