加入收藏 | 设为首页 | 会员中心 | 我要投稿 晋中站长网 (https://www.0354zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

mysql系统 MySQL-InnoDB-双写(Doublewrite Buffer)

发布时间:2022-12-03 09:00:39 所属栏目:MySql教程 来源:网络
导读: Doublewrite Buffer 为啥会有两次写?必要了解partial page write 问题 :
InnoDB 的Page Size一般是16KB,其数据校验也是针对这16KB来计算的,将数据写入到磁盘是以Page为单位进行操作的。

Doublewrite Buffer 为啥会有两次写?必要了解partial page write 问题 :

InnoDB 的Page Size一般是16KB,其数据校验也是针对这16KB来计算的,将数据写入到磁盘是以Page为单位进行操作的。而计算机硬件和操作系统,写文件是以4KB作为单位的,那么每写一个innodb的page到磁盘上,在os级别上需要写4个块.通过以下命令可以查看文件系统的块大小。

shell $ dumpe2fs /dev/vda1 |grep "Block size"

dumpe2fs 1.41.12 (17-May-2010)

Block size:4096

在极端情况下(比如断电)往往并不能保证这一操作的原子性,16K的数据,写入4K 时,发生了系统断电/os crash ,只有一部分写是成功的,这种情况下就是 partial page write 问题。有人会想到系统恢复后MySQL可以根据redolog 进行恢复,而mysql在恢复的过程中是检查page的checksum,checksum就是pgae的最后事务号,发生partial page write 问题时,page已经损坏,找不到该page中的事务号,就无法恢复。

mysql系统_mac 系统不支持 mysql_mysql获取系统当前日期

img

doublewrite缓冲区是一个硬盘存储区域,InnoDB在将从缓冲池中刷新的page写到InnoDB数据文件中相应的位置之前,会先将这些page写在doublewrite缓冲区。如果在写page的过程中出现了操作系统、存储子系统或意外的mysqld进程退出等情况,InnoDB可以在崩溃恢复过程中从doublewrite缓冲区中找到一个完整且正确的page副本。

尽管数据被写入两次,但doublewrite缓冲区并不需要两倍的I/O开销或两倍的I/O操作。数据是以一个大的顺序块写入doublewrite缓冲区(硬盘顺序写),对操作系统调用一个fsync()(除非innodb_flush_method设置为O_DIRECT_NO_FSYNC)。

doublewrite由两部分组成,一部分是内存中的doublewritebuffer,大小为2MB,另一部分是物理磁盘上共享表空间中连续的128个页,即2个区(extent),大小同样为2MB。在对缓冲池的脏页进行刷新时,并不直接写磁盘,而是会通过memcpy函数将脏页先复制到内存中的doublewritebuffer,之后通过doublewritebuffer再分两次,每次1MB顺序地写入共享表空间的物理磁盘上mysql系统,然后马上调用fsync函数,同步磁盘,避免缓冲写带来的问题。在这个过程中,因为doublewrite页是连续的,因此这个过程是顺序写的,开销并不是很大。在完成doublewrite页的写入后,再将doublewritebuffer中的页写入各个表空间文件中,此时的写入则是离散的。

引用自:姜承尧. MySQL技术内幕:InnoDB存储引擎(第2版) (数据库技术丛书) (Chinese Edition) (p. 106). 机械工业出版社. Kindle 版本.

在MySQL 8.0.20之前,doublewrite缓冲区存储区位于InnoDB系统表空间中。从MySQL 8.0.20开始,doublewrite缓冲区存储区位于doublewrite文件中。

以下变量用于doublewrite缓冲区配置:

变量innodb_doublewrite控制是否启用doublewrite缓冲区。在大多数情况下,它默认是启用的。禁用doublewrite缓冲区,设置innodb_doublewrite为OFF。如果您更关心性能而不是数据完整性,可以考虑禁用doublewrite缓冲区,例如在执行基准测试时可能会出现这种情况。

从MySQL 8.0.30, innodb_doublewrite支持DETECT_AND_RECOVER和DETECT_ONLY设置。

“DETECT_AND_RECOVER”设置与“ON”设置相同。有了这个设置,doublewrite缓冲区就完全启用了,数据库page内容被写入doublewrite缓冲区,在恢复期间访问该缓冲区以修复不完整的页面写入。

使用DETECT_ONLY设置,只有元数据被写入doublewrite缓冲区。数据库page内容不会写入doublewrite缓冲区,恢复也不会使用doublewrite缓冲区来修复未完成的页写入。此轻量级设置仅用于检测不完整的页面写入。

MySQL 从8.0.30版本开始,支持动态更改innodb_doublewrite设置,可以在ON, DETECT_AND_RECOVER和DETECT_ONLY之间切换使用doublewrite缓冲区。MySQL不支持在启用双写缓冲区和OFF设置之间进行动态更改,反之亦然。

如果doublewrite缓冲区位于支持原子写的Fusion-io设备上,自然可以关闭doublewrite缓冲区,使用Fusion-io原子写进行数据文件写操作。但是,请注意innodb_doublewrite设置是全局的。当禁用doublewrite缓冲区时,将禁用所有数据文件,包括不在Fusion-io硬件上的数据文件。该特性仅在Fusion-io硬件上支持,仅能在Linux操作系统上Fusion-io NVMFS上启用。为了充分利用该特性,建议使用innodb_flush_method设置O_DIRECT。

innodb_doublewrite_dir变量(在MySQL 8.0.20中引入)定义了InnoDB创建双写文件的目录。如果未指定目录,则在innodb_data_home_dir目录中创建doublewrite文件,默认为data目录。

哈希符号#会自动加到指定的目录名前面,以避免与模式名(schema)冲突。然而,如果在目录名中出现前缀"."、"#"或者"/",则不在目录名前面加上散列符号#。

理想情况下,doublewrite目录应该放在最快的可用存储介质上。

变量innodb_doublewrite_files定义了doublewrite文件的数量。默认情况下,为每个缓冲池实例创建两个doublewrite文件:一个刷新列表doublewrite文件和一个LRU列表doublewrite文件。

刷新列表doublewrite文件用于从缓冲池刷新列表刷新的页面。刷新列表双写文件的默认大小是InnoDB页面大小 * doublewrite page 字节。

LRU列表doublewrite文件用于从缓冲池LRU列表刷新的页面。它还包含用于single page刷新的slot。LRU列表doublewrite文件的默认大小是InnoDB页面大小* (doublewrite pages +(512 /缓冲池实例数)),其中512是为single page刷新预留的槽位(slot)总数。

同一时间,至少有两个doublewrite文件。doublewrite文件的最大数量是缓冲池实例数量的两倍。(缓冲池实例的数量由innodb_buffer_pool_instances变量控制。)

双写文件名的格式为:"#ib_page_size _ file_number.dblwr"(或.bdblwr和DETECT_ONLY设置)。例如,下面的doublewrite文件是为一个MySQL实例创建的,实例有一个InnoDB大小为16KB page和

mysql# ib_16384_0.dblwr# ib_16384_1.dblwr

innodb_doublewrite_files变量用于高级性能调优。默认设置应该适合大多数用户。

innodb_doublewrite_pages变量(在MySQL 8.0.20中引入)控制每个线程doublewrite页面的最大数量。如果不指定值,innodb_doublewrite_pages将设置为innodb_write_io_threads值。此变量用于高级性能调优。默认值应该适合大多数用户。

innodb_doublewrite_batch_size变量(在MySQL 8.0.20中引入)控制在批处理中写入的doublewrite页面的数量。此变量用于高级性能调优。默认值应该适合大多数用户。

从MySQL 8.0.23开始,InnoDB自动加密属于加密表空间的doublewrite page文件(参见15.13节“InnoDB Data-at-Rest Encryption”)。同样,属于页压缩表空间的doublewrite page文件也被压缩。因此,doublewrite文件可以包含不同的page类型,包括未加密和未压缩的page、加密的page、压缩的page以及加密和压缩的page。

double write的缺点是什么?

位于共享表空间上的double write buffer实际上也是一个文件,写DWB会导致系统有更多的fsync操作, 而硬盘的fsync性能,所以它会降低mysql的整体性能。

但是并不会降低到原来的50%。 这主要是因为:

double write 是一个连接的存储空间, 所以硬盘在写数据的时候是顺序写, 而不是随机写, 这样性能更高。将数据从double write buffer写到真正的segment中的时候, 系统会自动合并连接空间刷新的方式, 每次可以刷新多个pages。

两次写的作用

在数据库启动时(异常关闭的情况下),都会做数据库恢复(redo)操作,恢复的过程中,数据库都会检查页面是不是合法(校验等等),如果发现一个页面校验结果不一致,则此时会用到两次写这个功能,这个特点也正是为了处理这样的错误而设计的。

此时的操作很明白了,将两次写的2个BLOCK(簇)都读出来,然后将所有这些页面写回到对应的页面中去,那么这时可以保证这些页面是正确的,并且是在写入前已经更新过的(最新数据)。在写回对应页面中去之后,那么就可以在这基础上继续做数据库恢复了,之后则不会再遇到这样的问题了,因为已经将最后有可能产生写断裂的数据页面都恢复了。

如果是写doublewrite buffer本身失败,那么这些数据不会被写到磁盘,InnoDB此时会从磁盘载入原始的数据,然后通过InnoDB的事务日志来计算出正确的数据,重新写入到doublewrite buffer。

(编辑:晋中站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!