1. 程式人生 > 其它 >innodb關鍵特性之double write 02

innodb關鍵特性之double write 02

1.前言

  如果說insert buffer帶給innodb儲存引擎的是效能上的提升,那麼doublewrite(兩次寫),帶給innodb儲存引擎的是資料頁的可靠性

2.部分寫失效

  當發生資料庫宕機時,可能innodb儲存引擎正在寫入某個頁到表中,而這個頁只寫了一部分,比如16kb的頁,只寫了4kb,之後就發生了宕機,這種現象被稱為部分寫失效(partial page write).在innodb儲存引擎未使用doublewrite技術前,曾經出現過因為部分寫失效而導致資料丟失的現象。

3.錯誤區

  可能有些DBA認為若果發生寫失效了話,可以通過重做日誌進行恢復,但是你在用它進行恢復的時候,必須要知道重做日誌記錄的是對頁的物理操作,如偏移量800,寫‘aaa’記錄,如果這個頁的本身發生了損壞,再對其進行重做是沒有意義的。因此,在應用重做日誌之前,使用者需要一個頁的副本,當寫入失效發生時,先通過頁的副本來還原該頁,再進行重做,這就是doublewrite. 圖如下:

  

4.doublewrite

  doublewrite有兩部分組成,一部分是記憶體中的doublewrite buffer,大小2MB,另一部分是物理磁碟上共享表空間中連續的128個頁,即2個區,大小同樣為2MB,在對緩衝池的髒頁進行重新整理時,並不直接寫磁碟,而是會通過memcpy函式將髒頁先複製到記憶體的doublewriter buffer,之後通過doublewrite buffer在分兩次,每次1MB順序寫入共享表空間的物理磁碟上,然後馬上呼叫fsync函式,同步磁碟,避免緩衝寫帶來的問題,在這個過程中,因為doublewrite頁是連續的,因此這個過程是順序寫的,開銷並不是很大,在完成doublewrite頁的寫入後,再將doublewrite buffer中的頁寫入各個表空間檔案中,此時的寫入則是離散的

。可以通過以下命令觀察doublewrite執行情況

root@localhost 10:51:  [(none)]> show global status like 'innodb_dblwr%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Innodb_dblwr_pages_written | 12    |         #表示已經寫入到雙寫緩衝中的頁數
| Innodb_dblwr_writes        |
1 | #已經執行完成的doublewrite寫操作的次數 +----------------------------+-------+

如果發現系統在高峰是的innodb_dblwr_pages_written:innodb_dblwr_writes遠遠小於64:1,那麼可以說明系統寫入壓力並不高。這裡需要注意的是:開啟doublewrite後,每次髒頁重新整理必須要先寫doublewrite,而doublewrite存在於磁碟上的是兩個連續的區,每個區由連續的頁組成,一般情況下一個區最多有64個頁,所以一次IO寫入應該可以最多寫64個頁。

5.doublewrite恢復過程

  資料恢復有三種情況:

  第一種:髒資料寫磁碟成功

  刷盤成功,找檢查點,進行前滾、回滾就行了。

  第二種:共享表空間ibdata寫失敗

  如果是寫共享表空間失敗,那麼這些資料不會被寫到資料檔案,資料庫會認為這次刷盤從沒發生過,MySQL此時會從磁碟載入原始的資料,然後找檢查點,redo log前滾、回滾就行了。

  第三種:髒資料刷資料檔案失敗

  寫共享表空間成功,但是寫資料檔案失敗,在恢復的時候,MySQL直接比較頁面的checksum,如果不對的話,直接從共享表空間的double write中找到該頁的一個最近的副本,將其複製到表空間檔案,再應用redo log,就完成了恢復過程。因為有副本所以也不擔心表空間中資料頁是否損壞。  

6.檢視doublewrite是否開啟 

root@localhost 10:51:  [(none)]> show variables like '%double%';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| innodb_doublewrite | ON    |
+--------------------+-------+

  這裡也可以在配置檔案中進行配置,不配置的話預設是開啟的,如果想要關閉doublewrite的話,可以用skip_innodb_doublewrite引數

7.場景

  首先doublewrite這個特性在Mysql中是預設開啟的,如果我們對於需要提供資料高可靠性的主伺服器(master server),任何時候使用者都應該確保開啟doublewrite功能

  不過如果使用者有多個從伺服器(slave server),需要提供較快的功能(如在slave server上做的是RAID0),可以關閉該特性,還有的檔案系統本身就提供了部分寫失效的防範機制,如ZFS檔案系統,在這種情況下,使用者就不要啟動doublewrite了。