[MySQL]InnoDB特性之-兩次寫
今天我們來介紹InnoDB存儲引擎的第二個特性 - 兩次寫(doublewrite),如果說插入緩沖是為了提高寫性能的話,那麼兩次寫是為了提高可靠性,犧牲了一點點寫性能。
部分寫失效
想象這麼一個場景,當數據庫正在從內存向磁盤寫一個數據頁時,數據庫宕機,從而導致這個頁只寫了部分數據,這就是部分寫失效,它會導致數據丟失。這時是無法通過重做日志恢復的,因為重做日志記錄的是對頁的物理修改,如果頁本身已經損壞,重做日志也無能為力。
兩次寫機制
從上面分析我們知道,在部分寫失效的情況下,我們在應用重做日志之前,需要原始頁的一個副本,兩次寫就是為了解決這個問題,下面是它的原理圖:
兩次寫需要額外添加兩個部分:
1)內存中的兩次寫緩沖(doublewrite buffer),大小為2MB
2)磁盤上共享表空間中連續的128頁,大小也為2MB
其原理是這樣的:
1)當刷新緩沖池髒頁時,並不直接寫到數據文件中,而是先拷貝至內存中的兩次寫緩沖區。
2)接著從兩次寫緩沖區分兩次寫入磁盤共享表空間中,每次寫入1MB
3)待第2步完成後,再將兩次寫緩沖區寫入數據文件
這樣就可以解決上文提到的部分寫失效的問題,因為在磁盤共享表空間中已有數據頁副本拷貝,如果數據庫在頁寫入數據文件的過程中宕機,在實例恢復時,可以從共享表空間中找到該頁副本,將其拷貝覆蓋原有的數據頁,再應用重做日志即可。
其中第2步是額外的性能開銷,但由於磁盤共享表空間是連續的,因此開銷不是很大。可以通過參數skip_innodb_doublewrite禁用兩次寫功能,默認是開啟的,強烈建議開啟該功能。