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个系统页)
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提供了崩溃恢复功能,