1.1 什么是double write
MySQL的数据页默认是16K,而文件系统的数据页是4K,IO操作是按页为单位就行读写的。这就可能出现数据库对一个16k的数据页修改后,操作系统开始进行写磁盘,但是在这个过程中数据库宕机导致没有完全将16K数据页写到磁盘上。数据库重启后,校验数据页,发现有数据页不完整,就起不来了(redo是基于完整数据页进行的恢复)。
为了解决这个问题,MySQL引入了double write这个特性。double write针对的是脏数据,提高innodb的可靠性,用来解决部分写失败(partial page write)。为了数据的持久性,脏数据需要刷新到磁盘上,而double write就产生在将脏数据刷盘的过程中。刷盘是一份脏数据写到共享表空间ibdata中,一份写到真正的数据文件永久的保存。写了两次脏数据,就叫double wriete。
1.2 double write原理
简单来说,double write就是将修改后的脏页先放到double write buffer区,这个区占用2M内存空间,buffer空间满或其他条件触发,使double write buffer存的脏页先写到共享表空间(在MySQL 8.0.20之前,doublewrite缓冲区存储区位于InnoDB系统表空间中。从MySQL 8.0.20开始,doublewrite缓冲区存储区位于doublewrite文件中),之后在写入数据文件。这个时候如果写了不完整的页,可以用共享表空间中完整的页加以覆盖,数据页完整了,数据库也就可以拉起了,之后的各种恢复就看redo log的了。redo log是按数据块的方式记录日志的,它是根据偏移量来记录修改。尽管数据被写入两次,但双写缓冲区不需要两倍的I / O开销或两倍的I / O操作。只需一次fsync()调用操作系统。数据就可以按较大的顺序块写入doublewrite缓冲区(除非 innodb_flush_method设置为 O_DIRECT_NO_FSYNC)。
8.0.20后,在默认情况下,为每个缓冲池实例创建两个双写文件:刷新列表双写文件和LRU列表双写文件。
刷新列表双写文件用于从缓冲池刷新列表中刷新的页面。刷新列表doublewrite文件的默认大小是InnoDB page size * doublewrite page bytes.。
LRU列表双写文件用于从缓冲池LRU列表中刷新的页面。它还包含用于单页刷新的插槽。LRU列表双写文件的默认大小为InnoDB page size * (doublewrite pages + (512 / the number of buffer pool instances)),其中512是为单页刷新保留的插槽总数。
至少有两个双写文件。双写文件的最大数量是缓冲池实例数量的两倍。
redolog写入的单位就是512字节,也就是磁盘IO的最小单位,所以无所谓数据损坏。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




