「这是我参与 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
的关特性两次写,该特性保证了数据存储的可靠性,通过内存中的缓存区和共享磁盘中的表空间配合实现数据的可靠性。