Doublewrite缓冲区是一块存储区域,InnoDB刷脏时,在将页面从buffer pool写到磁盘上的InnoDB数据文件中之前,会现将页面写入这块区域。如果在写入页面时,操作系统,存储子系统,或mysqld进程发生未知故障而崩溃,InnoDB可以在崩溃恢复时从doublewrite缓冲区中找到这个页面的副本。
虽然数据被写入了两次,doublewrite缓冲区却不需要两倍的I/O负载和I/O操作次数。数据写入doublewrite缓冲区时是按照很大的区块顺序写入的,只是调用操作系统的fsync()函数(除了在innodb_flush_method被设置为o_direct_no_fsync的情况下)。
在MySQL8.0.20之前,doublewrite缓冲区是InnoDB系统表空间的一部分。从MySQL8.0.20开始,doublewrite缓冲区被移动到了独立的doublewrite文件夹内中。下面的变量提供了doublewrite缓冲区的相关设置:
- innodb_doublewrite innodb_doublewrite变量控制是否开启doublewrite缓冲区。大多数情况下默认开启。要禁用doublewrite缓冲区,将inno_db_doublewrite设置为OFF。如果相比数据一致性,你更关心性能(比如在性能测试时),可以考虑禁用doublewrite缓冲区。
从MySQL8.0.30开始,innodb_doublewrite支持DETECT_AND_RECOVER和DETECT_oNLY选项。 DETECT_AND_RECOVER选项和ON选项一样。在选择这个选项时,doublewrite缓冲区被全面启用,会将数据库页面写入doublewrite缓冲区,会通过缓冲区来恢复不完整的数据写入操作。 DETECT选项,只有元数据被写入doublewrite缓冲区。数据库页面内容不会被写入doublewrite缓冲区,恢复时也不会使用doublewrite缓冲区来修复不完整的页面写入。这个轻量级的选项只是用来检测未完成的页面写入。 MySQL8.0.30以后,支持动态设置innodb_doublewrite来开启doublewrite缓冲区,选项是:ON,DETECT_AND_RECOVER和DETECT_ONLY。MySQL不支持在两个开启doublewrite缓冲区和关闭doublewrite缓冲区的配置之间动态切换。
如果doublewrite缓冲区位于支持原子写入的融合io设备上,doublewrite缓冲区会被自动禁用,写入数据文件时会使用融合设备的原子写入。但是,要记住innodb_doublewrite设置是全局的。当禁用doublewrite缓冲区时,所有的数据文件都不会使用doublewrite缓冲区,这也包括那些不在融合设备上的。这个特性只支持linux系统上的融合io NVMFS。想要充分利用这个特性,建议将innodb_flush_method设置为O_DIRECT。
- innodb_doublewrite_dir 变量innodb_doublewrite_dir(在MySQL8.0.20中引入)定义了InnoDB创建doublewrite文件的目录。如果没有指定目录,doublewrite文件会被创建在innodb_data_home_dir目录下,这也是默认的数据目录。 指定的目录名称前会被添加hash标志前缀"#",以避免和数据库名称重复。但是,如果在指定的目录名称中有前缀’.’,‘#’,或’/’,就不会添加。
理想情况下,doublewrite目录应该位于最快的存储设备上。
- innodb_doublewrite_files 变量innodb_doublewrite_files定义了doublewrite文件的数量。默认情况下,每个buffer pool实例创建2个:一个用于flush链表,另一个用于LRU链表。用于flush链表的doublewrite文件是用于buffer pool中的flush链表的页面。默认大小是InnoDB页大小doublewrite页面。 用于LRU链表的doublewrite文件是用于buffer pool中的LRU链表的页面。它也包含了用于单页刷新的槽。默认大小是InnoDB页大小(doublewrite页数+(512/buffer pool实例数)),其中512是用于单页面刷新的槽的总数。
最少有两个doublewrite 文件。最大值是buffer pool实例数的两倍(buffer pool实例数由变量innodb_buffer_pool_instances控制)。
doublewrite文件名的格式是:#ib_page_size_file_number.dblwr(或是DETECT_ONLY && .bdblwr)。例如,下面的doublewrite文件所在是MySQL实例的InnoDB页面大小是16KB,单一buffer pool实例:
#ib_16384_0.dblwr#ib_16384_1.dblwr
innodb_doublewrite_files变量是用于高级性能调优的。默认设置应该能满足大多数用户的需求。
innodb_doublewrite_pages 变量innodb_doublewrite_pages(MySQL8.0.20引入)控制着每个线程的doublewrite页数的最大值。如果没有指定这个值,这个变量被设置成innodb_write_io_threads的值。这个变量用于高级性能调优,默认值应该能满足大部分用户的需求。
innodb_doublewrite_batch_size 这个变量是在MySQL8.0.20中引入,控制着每次写入的doublewrite 页面数量。这个变量用于高级性能调优,默认值应该能满足大部分用户的需求。
从MySQL8.0.23,InnoDB会对属于加密表空间的doublewrite文件页面进行自动加密(见章节 15.13,“InnoDB Data-at-Rest Encryption”。同样的,属于压缩页面表空间的doublewrite页面也会被压缩。因此,doublewrite文件能包含多种类型的页面,包括未压缩页面,加密页面,压缩页面,以及压缩并加密的页面。