InnoDB 关键特性-两次写

155 阅读3分钟

「这是我参与 2022 首次更文挑战的第 24 天,活动详情查看:2022 首次更文挑战

泽无水,困。君子以致命遂志。

前言

前文讲述了 mysql 数据库 InnoDB 引擎关键特性-插入缓存,本文继续介绍 InnoDB 的特性两次写,插入缓存给 InnoDB 引擎带来了性能上的提升,两次写则是保证了 InnoDB 存储引擎数据页的可靠性。

两次写

当数据库放生宕机时,可能 InnoDB 存储引擎正在把某个页的数据写入到数据表中,这个页只写了一部分,我们知道一个数据页的大小默认是 16KB,如果只写了一半就发生故障,那么就会出现部分写失效的情况,两次写的出现就解决了这个问题。

如果发生了写失效的情况,可以通过重做日志进行恢复,重做日志是对页的物理操作,如果这个页本身发生了损坏,再对其进行重做是没有意义的。在应用重做日志前,用户需要一个页的副本,当发生写失效的时候,先通过页的副本来还原页,在进行重做,这就是 double write

InnoDB 存储引擎 doble write 架构图如下图所示:

doble write 分为两个部分,一部分是内存中的缓存区 doublewrite buffer ,大小为 2MB,另外一部分为物理磁盘上的共享表空间,这是一块儿连续的空间,其大小为 128 个页,即两个区,大小同样为2MB

在将内存中的脏页刷新到磁盘时,第一步会调用系统方法 memcpy 将脏页中的数据复制到内存中的双写缓冲区(double write buffer),之后再分两次,每次 1MB 顺序地写入共享表空间的物理磁盘上,最后调用 fsync 函数同步写入磁盘文件,避免缓冲写带来的问题。在整个过程中,doublewrite 页是连续的,整个过程是顺序写的,所以开销并不是很大。在数据写入 doublewrite 页后,再将 doublewrite buffer 中的页写入各个表空间文件中,此时的数据写入是离散的。

从配置文件可以看到 doublewrite 一共写了 92285888 页,但是实际写入的数据为 6930989 页,其比例为 13:1,如果发现系统在高峰时超过了这个值,就代表着数据库的写数据压力巨大。

如果操作系统在将数据写入磁盘的过程中发生了崩溃,在恢复的过程中,InnoDB 存储引擎可以从共享表空间中的 doublewrite 中找到该页的一个副本,将其复制到表空间文件,再应用重做日志。

如下图所示,可以根据 show status like "innodb_buffer%" 来查看缓冲池的一些配置情况。

# 缓冲池中刷新到磁盘页的数量
Innodb_buffer_pool_pages_flushed

总结

本文讲述了 InnoDB 的关特性两次写,该特性保证了数据存储的可靠性,通过内存中的缓存区和共享磁盘中的表空间配合实现数据的可靠性。