什么是寫失效,如何解決寫失效問題
寫失效是指在Mysql數據頁在寫入磁盤的過程中由于系統宕機或其他原因導致數據頁一部分部分寫入成功,一部分寫入失敗,最終造成數據頁損壞的情況。這種情況會導致數據丟失并且無法通過redo log恢復(redo log記錄的是數據頁的物理操作,而非完整數據頁)。
1、為什么出現寫失效問題
lnnoDB存儲引擎中緩存頁和操作系統的頁大小不一致,lnnoDB頁大小默認為16K(可以設置),操作系統頁默認大小為4K,當InnoDB的頁寫入到磁盤時,一個頁需要分4次寫,如下圖所示:
圖片
如果當存儲引擎正在寫入頁的數據到磁盤時發生了宕機,可能出現頁只寫成功一部分的情況,如下圖所示:
圖片
上圖這種情況就做部分寫失效,會導致數據丟失的問題。
2、Mysql如何解決寫失效
為了解決寫失效問題,Mysql引入了雙寫緩沖區(Double Write Buffer,它是InnoDB存儲引擎的一種機制,用于解決部分寫失效的問題,提高數據完整性和可靠性),InnoDB存儲引擎中,系統表空間的有雙寫緩沖區,如下圖所示:
圖片
Doublewrite Buffer是內存+磁盤的結構,在內存結構中,Doublewrite Buffer由128個頁構成,大小是2MB,這些頁在內存中以Doublewrite Buffer的形式存在,如下圖所示:
圖片
在磁盤結構中,Doublewrite Buffer在系統表空間上是128個頁(2個區,每個大小是1M),總的大小是2M。
雙寫緩沖區的原理是雙寫緩沖區通過在數據頁寫入磁盤之前,先將數據頁寫入系統表空間中的Doublewrite buffer區域,確保即使在寫入過程中發生宕機,也可以通過該臨時區域恢復損壞的數據頁,如下圖所示:
圖片
當有數據頁(臟頁)要被寫入數據文件時,首先將頁數據通過函數拷貝至內存中的Doublewrite buffer中,如下圖所示:
圖片
Doublewrite buffer每次寫1MB數據到磁盤上的共享表空間上,在共享表空間中會單獨開辟2M連續的空間專門給Doublewrite buffer刷臟頁用,由于這個存儲空間是連續的并且寫入磁盤還是順序寫,所以數據頁同步到系統表空間的性能很高,執行的速度也很快。
完成同步系統表空間后,Doublewrite buffer再將臟頁寫入實際的各個表空間文件中,這時寫入就是離散的了,如下圖所示:
圖片
這個上述的過程中,第一次寫入到系統表空間上,第二次寫入實際的表空間中,這個過程涉及到兩次寫入,這過程我們稱之為雙寫,完成的過程如下圖所示:
圖片
當Mysql刷臟頁到磁盤上出現崩潰時,在系統崩潰恢復過程中,雙寫緩沖區的作用就出來了,如下圖所示:
圖片
如果數據頁在寫入過程中發生損壞,InnoDB存儲引擎會從系統表空間中的雙寫緩沖區中查找該頁的完整副本,并將其恢復到數據文件中,然后再結合redo log完成崩潰恢復的工作。
總結:
(1)寫失效是指在數據頁寫入磁盤的過程中,由于系統宕機或其他原因導致數據頁部分寫入成功,部分寫入失敗,從而造成數據頁損壞的情況。
(2)雙寫緩沖區通過在數據頁寫入磁盤之前,先將數據頁寫入系統表空間中,確保即使在寫入過程中發生宕機,也可以通過系統表空間中的數據頁副本恢復損壞的數據頁。
(3)雙寫緩沖區的大小為2MB,由128個頁組成,分為內存部分和磁盤部分。
(4)雙寫緩沖區會引入一定的性能開銷,但在大多數情況下,這種開銷完全值得,因為它提供了更高的安全性和可靠性。
(5)在Mysql的Innodb存儲引擎中,redo log和Doublewrite buffer是配合工作的,目的是確保數據的持久性和恢復能力。在恢復過程中,如果存在損壞的數據頁,Innodb首先會去雙寫緩沖區文件中找數據頁副本,用副本嘗試恢復損壞的數據頁,然后再應用redo log完成數據的同步。































