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

数据库,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

【mysql】Innodb三大特性之double write的更多相关文章

  1. Mysql InnoDB三大特性-- change buffer

    Mysql InnoDB三大特性-- change buffer

  2. Mysql InnoDB三大特性-- 自适应hash index

    Mysql InnoDB三大特性-- 自适应hash index

  3. Mysql InnoDB三大特性-- double write

    转自:http://www.ywnds.com/?p=8334 一.经典Partial page write问题? 介绍double write之前我们有必要了解partial page write( ...

  4. 【mysql】Innodb三大特性之adaptive hash index

    1.Adaptive Hash Indexes 定义 If a table fits almost entirely in main memory, the fastest way to perfor ...

  5. 【mysql】Innodb三大特性之insert buffer

    一.什么是insert buffer insert buffer是一种特殊的数据结构(B+ tree)并不是缓存的一部分,而是物理页,当受影响的索引页不在buffer pool时缓存 secondar ...

  6. innodb关键特性之double write

    # 脏页刷盘的风险 两次写的原理机制 1.解决问题 2.使用场景 3.doublewrite的工作流程 4.崩溃恢复 # doublewrite的副作用 1.监控doublewrite负载 2.关闭d ...

  7. MySQL学习(十一)double write 介绍 (半原创)

    复习 Innodb关键的特性 插入缓存 两次写 异步IO 刷新邻近页 自适应哈希索引 概述 double write 的主要的作用是保证写入数据库文件的可靠性.通俗地说就是一份数据写两个地方,当出现异 ...

  8. MySQL InnoDB特性:两次写(Double Write)

    http://www.ywnds.com/?p=8334 一.经典Partial page write问题? 介绍double write之前我们有必要了解partial page write(部分页 ...

  9. Mysql 三大特性详解

    Mysql 三大特性详解 Mysql Innodb后台线程 工作方式 首先Mysql进程模型是单进程多线程的.所以我们通过ps查找mysqld进程是只有一个. 体系架构 InnoDB存储引擎的架构如下 ...

随机推荐

  1. docker get 到的命令 (持续更新)

    删除容器:  docker rm containerID (is running) 删除not running的容器:  docker ps -a   然后  docker rm -f contain ...

  2. java代码将e.printStackTrace()写入log4j文件异常信息

    try { ... } catch (Exception e) { log.error( "failed!", e ); } 或者 try { ... } catch (Excep ...

  3. 2008技术内幕:T-SQL语言基础 单表查询摘记

    这里的摘抄来自<Microsoft SQL Server 2008技术内幕:T-SQL语言基础>,书中用到的案例数据库是这个 TSQLFundamentals2008 ,官网给出的连接是这 ...

  4. Android之在应用程序内部关注某人的微信

    Intent intent = new Intent(Intent.ACTION_VIEW); intent.setPackage("com.tencent.mm");//直接打开 ...

  5. Andorid之使用GMail后台偷偷发送邮件(不要干坏事噢=。 =)

    工具类: import java.util.Date; import java.util.Properties; import javax.activation.CommandMap; import ...

  6. Java 动态向 JTable 中添加数据

    import java.awt.Toolkit; import javax.swing.SwingUtilities; import javax.swing.UIManager; import jav ...

  7. 巧妙利用jQuery和PHP打造类似360安全卫士防火墙功能开关(类似iphone界面)效果

    安全卫士防火墙开启关闭的开关,可以将此功能应用在产品功能的开启和关闭功能上. 准备工作为了更好的演示本例,我们需要一个数据表,记录需要的功能说明及开启状态,表结构如下: CREATE TABLE `p ...

  8. 页面的缓存设置与meta的作用详细解释

    网上转的,来自JSP的,但是原理大同小异哦,有时间 写个asp.net版的 HTML的HTTP协议头信息中控制着页面在几个地方的缓存信息,包括浏览器端,中间缓存服务器端(如:squid等),Web服务 ...

  9. 校验IPv4和IPv6地址和URL地址

    1.校验IPV4地址: function validateIp(obj) { var ip=$(obj).val(); var re=/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;// ...

  10. QlikView图表显示同比数据

    数据准备例如以下: SalesData: LOAD Num(ID) as ID, Date(Date) as Date, Month, Num(Year) as Year, Num(Sales) as ...