Doublewrite架构¶
Doublewrite Buffer被MySQL放在官方文档目录的 "InnoDB On-Disk Structures" 中了,但真实情况是Doublewrite Buffer是内存+磁盘的结构。
背景¶
操作系统可以看成是一个程序,作为程序而言,都有最小处理单位的说法,我们常见的服务器一般都是Linux操作系统,对应文件系统的页(OS Page)就可以看成是Linux操作系统与文件系统交互的最小单位。
一般情况下,除了操作系统的页(OS Page)为4KB之外,其余程序的页(Page)都会大于等于操作系统的页大小,比如,Oracle的Page大小为8KB。
MySQL的Page大小也可以通过上面innodb_page_size参数指定,具体情况如下:
- <5.6版本时,不可调整;
- 5.6版本时,可自定义为8KB、4KB,但不能调大【调小是为了调高数据对齐概率】;
- 5.7以上,才可以改成32KB、64KB【且最好设置成默认值16KB的整数倍,这是全局选项,无法在MySQL运行过程中动态修改】。
说了这么多,其实大多数情况一般都不用修改,使用默认值即可。
有点扯远了。我们知道操作系统的页大小和MySQL的页大小了,而且MySQL程序是跑在Linux操作系统上的,所以可以得出如下结论:
MySQL将Buffer Pool中一个数据页刷入磁盘,要写4个文件系统里的页(也可以说成一个MySQL数据页映射4个系统页)
当数据库将脏页(修改过的页)从缓冲池(Buffer Pool)刷新到磁盘时,可能会因为以下原因导致数据页损坏:
- 部分写入 :操作系统或磁盘控制器在写入过程中发生故障(如断电、崩溃等),导致数据页未完全写入磁盘。
- 不一致状态 :数据页只写了一部分,导致页内容不完整或损坏。
Doublewrite解决了什么问题?¶
为了解决**部分页面写入**问题(Partial Page Write)。
MySQL写入修改时刷新整个页面(默认16KB),而不仅仅是刷新页面中已更改的记录。
而操作系统的单次io,一般是512byte为单位的。在断电,OS crash(操作系统崩溃)情况下可能会丢失数据。
Doublewrite是指哪两次写入?¶
- 写Doublewrite buffer,注意: Doublewrite buffer**是磁盘不是内存**。
- 写入数据文件。
写入顺序:先写doublewrite buffer,写**成功后**再写到数据文件。
Doublewrite buffer存储区位于什么地方?¶
- 在MySQL 8.0.20之前:位于InnoDB系统表空间中(ibdata文件)
- 从MySQL 8.0.20开始:位于doublewrite文件中,文件由innodb_doublewrite_dir和innodb_doublewrite_files 配置确定
# 指定df文件的存储路径,默认是跟innodb_data_home_dir,一般就是数据目录datadir
innodb_doublewrite_dir=innodb_data_home_dir
# 指定db文件的数量,默认为每个buffer_pool_instance创建2个,最小是2,最大是256
innodb_doublewrite_files=
innodb 什么时候将脏页写入Doublewrite buffer中?¶
由以下几个参数决定:
- innodb_max_dirty_pages_pct_lwm: 低位水平标记,达到该值将启动缓冲刷新,默认为10(百分比,脏页/缓冲池)
- innodb_max_dirty_pages_pct: 脏页数量与缓冲池比例阈值,默认为90
- 如果开启自适应刷新(Adaptive Flushing)InnoDB根据重做日志生成的速度和当前的刷新率,使用自适应刷新算法来动态调整刷新率。
如何查看双写缓冲区的大小?¶
8.0.20之前,Doublewrite buffer是系统表空间中连续的128个页(每个页16k),总共2M
8.0.20开始的doublewrite buffer由单独文件保存:
# Doubliewrite文件命名
# #_页大小_文件编号.dblwr
# 页大小一般默认就是16KB,由innodb_page_size控制
-rwxrwxrwx 1 root root 192K 7月 6 23:15 '#ib_16384_0.dblwr'
-rwxrwxrwx 1 root root 8.2M 7月 6 23:16 '#ib_16384_1.dblwr'
Doublewrite buffer从脏页刷新速度由哪些参数控制?¶
清洗线程数由innodb_page_cleaners配置(8.0.20版本默认为4),单个线程最多每次写入doublewrite buffer 的页面数由innodb_doublewrite_pages变量控制, 在默认情况下为innodb_write_io_threads的值(默认4), 每秒写入次数还受到innodb_io_capacity (定义了每秒I / O操作数,默认值200)和innodb_io_capacity_max(InnoDB在由后台任务每秒执行的最大IOPS数 )控制。
为什么有了redo log,还需要doublewrite buffer?¶
一般都认为,redo提供了崩溃恢复功能,
16K原子写MySQL¶
在数据库领域,提升数据库性能的方法很多,但其中效果比较显著的就包括16K原子写的MySQL,它的效果在于可以相对显著地提升MySQL服务的读写性能,并且还有降低写放大等优势。而要实现16K原子写的特性,不仅需要数据库软件本身的支持,还需要硬件和文件系统层面的支持。
https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/configure-twp.html
"4K对齐"指的是符合"4K扇区"定义格式化过的硬盘,并且按照"4K扇区"的规则写入数据。
4K对齐是一种高级硬盘使用技术,用特殊方法将文件系统格式与硬盘物理层上进行契合,为提高硬盘寿命与高效率使用硬盘空间提供解决方案。
产生背景机械硬盘在储存数据时,一直都是以512byte大小的扇区(Sector)为单位分割进行读写。
随着硬盘容量的不断提升,这种分配标准已经越来越显的不合时宜。因此,硬盘生产厂商们决定将扇区容量扩大到4KB,也就是“4K扇区”。
在NTFS6.X以前的规范中,数据的写入点正好会介于两个4K扇区的之间,也就是说即使是写入数据量非常小,也会使用到两个4K扇区,显然这样对写入速度和读取速度都会造成比较大的影响。为此对于“4K不对齐”的情况来说,一定要修改成“4K对齐”才好,否则不但会极大的降低数据写入和读取速度,还会造成硬盘不必要的写入次数,减少使用寿命。将硬盘调整为4K对齐后,可以提升硬盘的读写速度。要实现4K对齐,首先要开启硬盘的AHCI模式,然后使用4K对齐工具进行4K对齐,进而减少读写次数,使数据传输更为高效。
原理电脑传统机械硬盘的每个扇区一般大小为512字节;当使用某一文件系统将硬盘格式化时,文件系统会将硬盘扇区、磁道与柱面统计整理并定义一个簇为多少扇区方便快速存储。
显然,如果有16K对齐的磁盘,可以显著提升MySQL性能。