透過doublewrite計數來預估系統寫入壓力
引自《MYSQL技術內幕innodb儲存引擎》
mysql有一個doublewrite的機制來保護資料的可靠性。想象一個場景,當資料庫意外宕機時,某一個數據頁正在寫入。這個頁可能只寫了一部分,比如寫了16K的前4K,這種情況我們稱之為部分寫失效(partial page write)。
有人會說如果發生了寫失效,可以通過重做日誌來恢復。這個是一個辦法。但是重做日誌記錄的是對資料頁的物理操作,如偏移量100,寫‘abc'記錄。但是,如果這個頁本身已經損壞,再對其進行重做是沒有意義的。這就是說在apply redo log時,我們需要一個頁的副本,當寫入失效時,先通過頁的副本來還原該頁,在進行重做,這就是double write。Innodb doublewrite的體系架構如圖:
doublewrite由兩部分組成:一部分是記憶體中的doublewrite buffer,大小為2MB;另一個部分是物理磁碟上共享表空間中連續的128個頁,即兩個區(extent),大小同樣為2MB。當緩衝池的髒頁重新整理時,並不直接磁碟,而是會通過memcpy函式將髒頁先考到記憶體中的doublewrite buffer中,然後通過doublewrite buffer分兩次,每次寫1MB到共享表空間的物理磁碟上,然後馬上呼叫fsync函式,同步磁碟,避免緩衝寫帶來的問題。在這個過程中,因為doublewrite頁是連續的,因此這個過程是順序寫的,開銷並不是很大。在完成doublewrite的寫入後,再將doublewrite buffer中的頁寫入各個表空間檔案中,此時的寫入則是離散的。
下面我們來看看doublewrite的執行狀態:
mysql> show global status like 'innodb_dblwr%';
+----------------------------+--------+
| Variable_name | Value |
+----------------------------+--------+
| Innodb_dblwr_pages_written | 876623 |
| Innodb_dblwr_writes | 62798 |
+----------------------------+--------+
2 rows in set (0.00 sec)
Innodb_dblwr_pages_written 是doublewrite寫的總的頁數,即一共寫入了876623頁,但實際寫入的次數innodb_dblwr_writes為62798。如果兩個計數的比例遠遠小於64:1,則說明系統寫入壓力並不高。
如果作業系統在將頁寫入磁碟的過程中崩潰了,在恢復過程中,innodb儲存引擎可以從共享表空間的doublewrite中找到改頁的一個副本,將其拷貝到表空間檔案,在應用重做日誌。
注: 引數skip_innodb_doublewrite可以禁止使用兩次寫入功能。
轉載於:https://blog.51cto.com/johnnywong/1660708