mysql的三大特性_【mysql】Innodb三大特性之double write
1、doublewrite buffer(mysql官方的介紹)
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
數(shù)據(jù)庫,OS和磁盤讀寫的基本單位是塊,也可以稱之為(page size)block size。
數(shù)據(jù)庫的塊一般為8K,16K;而OS的塊則一般為4K;IO塊則更小,linux內(nèi)核要求IO block size<=OS block size。
磁盤IO除了IO block size,還有一個(gè)概念是扇區(qū)(IO sector),扇區(qū)是磁盤物理操作的基本單位,而IO 塊是磁盤操作的邏輯單位,一個(gè)IO塊對(duì)應(yīng)一個(gè)或多個(gè)扇區(qū),扇區(qū)大小一般為512個(gè)字節(jié)。
所以各個(gè)塊大小的關(guān)系可以梳理如下:
DB block > OS block >= IO block > 磁盤 sector,而且他們之間保持了整數(shù)倍的關(guān)系。比如我的系統(tǒng)各個(gè)塊的大小如下,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
從上面的結(jié)果可以看到DB page=4*OS page=16*IO page=32*sector size
由于任何DB page的寫入,最終都會(huì)轉(zhuǎn)為sector的寫入,如果在寫磁盤的過程中,出現(xiàn)異常重啟,就可能會(huì)發(fā)生一個(gè)DB頁只寫了部分sector到磁盤,進(jìn)而出現(xiàn)頁斷裂的情況
InnoDB 的Page Size一般是16KB,其數(shù)據(jù)校驗(yàn)也是針對(duì)這16KB來計(jì)算的,將數(shù)據(jù)寫入到磁盤是以Page為單位進(jìn)行操作的。而計(jì)算機(jī)硬件和操作系統(tǒng),在極端情況下 (比如斷電)往往并不能保證這一操作的原子性,16K的數(shù)據(jù),寫入4K 時(shí),發(fā)生了系統(tǒng)斷電/os crash ,只有一部分寫是成功的,這種情況下就是 partial page write 問題。
很多DBA 會(huì)想到系統(tǒng)恢復(fù)后,MySQL 可以根據(jù)redo log
進(jìn)行恢復(fù),而mysql在恢復(fù)的過程中是檢查page的checksum,checksum就是pgae的最后事務(wù)號(hào),發(fā)生partial page
write 問題時(shí),page已經(jīng)損壞,找不到該page中的事務(wù)號(hào),就無法恢復(fù)
所以說,當(dāng)page 損壞之后,其實(shí)應(yīng)用redo是沒有意義的,這時(shí)候無法使用redo來恢復(fù),因?yàn)樵柬撘呀?jīng)損壞了,會(huì)發(fā)生數(shù)據(jù)丟失。
3、doublewrite
在InnoDB將BP中的Dirty Page刷(flush)到磁盤上時(shí),首先會(huì)將(memcpy函數(shù))Page刷到InnoDB tablespace的一個(gè)區(qū)域中,我們稱該區(qū)域?yàn)镈ouble write Buffer(大小為2MB,每次寫入1MB,128個(gè)頁)。在向Double write Buffer寫入成功后,第二步、再將數(shù)據(jù)拷貝到數(shù)據(jù)文件對(duì)應(yīng)的位置
當(dāng)?shù)诙竭^程中發(fā)生故障,也就是發(fā)生partial page write的問題。恢復(fù)的時(shí)候先檢查頁內(nèi)的checksum是否相同,不一致,則直接從doublewrite中恢復(fù)
1)如果寫dw buffer失敗,那么這些數(shù)據(jù)不會(huì)寫到磁盤,innodb會(huì)載入磁盤原始數(shù)據(jù)和redo日志比較,并重新刷到dw buffer。
2)如果寫dw buffer成功,但是刷新到磁盤失敗,那么innodb就不會(huì)通過事務(wù)日志來恢復(fù)了,而是直接刷新dw buffer中的數(shù)據(jù)。
4、對(duì)性能的影響
系統(tǒng)需要將數(shù)據(jù)寫兩份,一般認(rèn)為,Double Write是會(huì)降低系統(tǒng)性能的。peter猜測(cè)可能會(huì)有5-10%的性能損失,但是因?yàn)閷?shí)現(xiàn)了數(shù)據(jù)的一致,是值得的。Mark Callaghan認(rèn)為這應(yīng)該是存儲(chǔ)層面應(yīng)該解決的問題,放在數(shù)據(jù)庫層面無疑是犧牲了很多性能的。
事實(shí)上,Double Write對(duì)性能影響并沒有你想象(寫兩遍性能應(yīng)該降低了50%吧?)的那么大。在BP中一次性往往會(huì)有很多的Dirty Page同時(shí)被flush,Double Write則把這些寫操作,由隨機(jī)寫轉(zhuǎn)化為了順序?qū)憽6贒ouble Write的第二個(gè)階段,因?yàn)镈ouble Write Buffer中積累了很多Dirty Page,所以向真正的數(shù)據(jù)文件中寫數(shù)據(jù)的時(shí)候,可能有很多寫操作可以合并,這樣有可能會(huì)降低Fsync的調(diào)用次數(shù)。
基于上面的原因,Double Write并沒有想象的那么糟。另外,Dimitri在測(cè)試后,發(fā)現(xiàn)打開和關(guān)閉Double Write對(duì)效率的影響并不大。
5、doublewrite參數(shù)
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
總結(jié)
以上是生活随笔為你收集整理的mysql的三大特性_【mysql】Innodb三大特性之double write的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL多字段排序乱_Mysql OR
- 下一篇: ext springmvc mysql_