【mysql】Innodb三大特性之double write


1、doublewrite buffermysql官方的介紹

InnoDB uses a novel file flush technique called doublewrite. Before writing pages to the data files, InnoDB first writes them to a contiguous area called the doublewrite buffer. Only after the write and the flush to the doublewrite buffer have completed, does InnoDB write the pages to their proper positions in the data file. If there is an operating system, storage subsystem, or mysqld process crash in the middle of a page write, InnoDB can later find a good copy of the page from the doublewrite buffer during crash recovery.

Although data is always written twice, the doublewrite buffer does not require twice as much I/O overhead or twice as many I/O operations. Data is written to the buffer itself as a large sequential chunk, with a single fsync() call to the operating system.

To turn off the doublewrite buffer, specify the option innodb_doublewrite=0.

2、partial page write

 

數據庫,OS和磁盤讀寫的基本單位是塊,也可以稱之為(page size)block size。

數據庫的塊一般為8K,16K;而OS的塊則一般為4K;IO塊則更小,linux內核要求IO block size<=OS block size。

磁盤IO除了IO block size,還有一個概念是扇區(IO sector),扇區是磁盤物理操作的基本單位,而IO 塊是磁盤操作的邏輯單位,一個IO塊對應一個或多個扇區,扇區大小一般為512個字節。

所以各個塊大小的關系可以梳理如下:

 

DB block > OS block >= IO block > 磁盤 sector,而且他們之間保持了整數倍的關系。比如我的系統各個塊的大小如下,DB以mysql為例,OS以linux為例

DB block size

mysql> show variables like 'innodb_page_size';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| innodb_page_size | 16384 |
+------------------+-------+

OS block

[root@dev ~]# getconf PAGESIZE
4096

IO block size

[root@dev ~]# blockdev --getbsz /dev/sda1 
1024

sector size 

[root@dev ~]# fdisk -l | grep Sector
Sector size (logical/physical): 512 bytes / 512 bytes

從上面的結果可以看到DB page=4*OS page=16*IO page=32*sector size

由於任何DB page的寫入,最終都會轉為sector的寫入,如果在寫磁盤的過程中,出現異常重啟,就可能會發生一個DB頁只寫了部分sector到磁盤,進而出現頁斷裂的情況 

 

InnoDB 的Page Size一般是16KB,其數據校驗也是針對這16KB來計算的,將數據寫入到磁盤是以Page為單位進行操作的。而計算機硬件和操作系統,在極端情況下 (比如斷電)往往並不能保證這一操作的原子性,16K的數據,寫入4K 時,發生了系統斷電/os crash ,只有一部分寫是成功的,這種情況下就是 partial page write 問題。

很多DBA 會想到系統恢復后,MySQL 可以根據redo log 進行恢復,而mysql在恢復的過程中是檢查page的checksum,checksum就是pgae的最后事務號,發生partial page write 問題時,page已經損壞,找不到該page中的事務號,就無法恢復

所以說,當page 損壞之后,其實應用redo是沒有意義的,這時候無法使用redo來恢復,因為原始頁已經損壞了,會發生數據丟失。

3、doublewrite

在InnoDB將BP中的Dirty Page刷(flush)到磁盤上時,首先會將(memcpy函數)Page刷到InnoDB tablespace的一個區域中,我們稱該區域為Double write Buffer(大小為2MB,每次寫入1MB,128個頁)。在向Double write Buffer寫入成功后,第二步、再將數據拷貝到數據文件對應的位置

當第二步過程中發生故障,也就是發生partial page write的問題。恢復的時候先檢查頁內的checksum是否相同,不一致,則直接從doublewrite中恢復

1)如果寫dw buffer失敗,那么這些數據不會寫到磁盤,innodb會載入磁盤原始數據和redo日志比較,並重新刷到dw buffer。
2)如果寫dw buffer成功,但是刷新到磁盤失敗,那么innodb就不會通過事務日志來恢復了,而是直接刷新dw buffer中的數據。

4、對性能的影響

系統需要將數據寫兩份,一般認為,Double Write是會降低系統性能的。peter猜測可能會有5-10%的性能損失,但是因為實現了數據的一致,是值得的。Mark Callaghan認為這應該是存儲層面應該解決的問題,放在數據庫層面無疑是犧牲了很多性能的。

事實上,Double Write對性能影響並沒有你想象(寫兩遍性能應該降低了50%吧?)的那么大。在BP中一次性往往會有很多的Dirty Page同時被flush,Double Write則把這些寫操作,由隨機寫轉化為了順序寫。而在Double Write的第二個階段,因為Double Write Buffer中積累了很多Dirty Page,所以向真正的數據文件中寫數據的時候,可能有很多寫操作可以合並,這樣有可能會降低Fsync的調用次數。

基於上面的原因,Double Write並沒有想象的那么糟。另外,Dimitri在測試后,發現打開和關閉Double Write對效率的影響並不大。

5、doublewrite參數

mysql> show variables like "%double%";
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| innodb_doublewrite | ON    |
+--------------------+-------+
1 row in set (0.00 sec)

mysql> SHOW STATUS LIKE "%innodb_dblwr%";
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Innodb_dblwr_pages_written | 447   |
| Innodb_dblwr_writes        | 38    |
+----------------------------+-------+
2 rows in set (0.00 sec)

從上面可以看出, Flush了447次到doublewrite buffer中,寫文件共38次,則每次write合並了447/38次flush

 

參考文章

http://www.percona.com/blog/2006/08/04/innodb-double-write/
http://www.percona.com/doc/percona-server/5.5/performance/innodb_doublewrite_path.html?id=percona-server:features:percona_innodb_doublewrite_path
http://dev.mysql.com/doc/refman/5.0/en/innodb-disk-io.html
http://www.mysqlperformanceblog.com/2006/08/04/innodb-double-write/
http://www.facebook.com/note.php?note_id=107329775932
http://dimitrik.free.fr/blog/archives/2009/08/entry_86.html
http://www.cnblogs.com/cchust/p/3961260.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM