os: centos 7.4
db: mysql 5.7.28
版本
# cat /etc/centos-release
CentOS Linux release 7.4.1708 (Core)
#
# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 12
Server version: 5.7.28 MySQL Community Server (GPL)
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.28 |
+-----------+
1 row in set (0.00 sec)
mysql>
partial page write
innodb 的 page size 一般是16KB,其数据校验也是针对这 16KB 来计算的,将数据写入到磁盘是以Page为单位进行操作的。
而计算机硬件和操作系统,在极端情况下(比如断电)往往并不能保证这一操作的原子性,16K的数据,写入4K 时,发生了系统断电/os crash ,只有一部分写是成功的,这种情况下就是 partial page write 问题。
如果使用 mysql redolog 进行恢复时,就会检查 page 的 checksum(checksum 就是page的最后事务号),但是发生 partial page write 问题时,page已经损坏,找不到该page中的事务号,就无法恢复。
double write
这里需要提一下共享表空间,是在 ibdbata 文件中划出2M连续的空间,专门给 double write 刷脏页用的,说白了就是磁盘上2MB(128个页,2个区)连续空间。
mysql 为什么需要 double write,刷一次数据文件保存数据不就行了。
主要还是为了解决极端情况下的 partial page write 问题 ,当 mysql 将脏数据 flush 到 data file 的时候, 先使用 memcopy 将脏数据复制到内存中的 double write buffer ,之后通过 double write buffer 再分2次,每次写入1MB到共享表空间,然后马上调用fsync函数,同步到磁盘上,避免缓冲带来的问题,在这个过程中,doublewrite是顺序写,开销并不大,在完成doublewrite写入后,在将double write buffer写入各表空间文件,这时是离散写入。
如果发生了极端情况(断电),InnoDB再次启动后,发现了一个Page数据已经损坏,那么此时就可以从 doublewrite buffer 中进行数据恢复了。
默认 double write 是开启的,可以手动修改参数,禁止 double write
mysql> show global variables like '%double%';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| innodb_doublewrite | ON |
+--------------------+-------+
1 row in set (0.01 sec)
查看 status double write
mysql> show status like "%InnoDB_dblwr%";
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Innodb_dblwr_pages_written | 2 |
| Innodb_dblwr_writes | 1 |
+----------------------------+-------+
2 rows in set (0.00 sec)
double write 的缺点
位于共享表空间上的double write buffer实际上也是一个文件,写DWB会导致系统有更多的fsync操作, 而硬盘的fsync性能, 所以它会降低mysql的整体性能. 但影响并不是特别的大, 这主要是因为:
1、double write 是一个连接的存储空间, 所以硬盘在写数据的时候是顺序写, 而不是随机写, 这样性能更高.
2、将数据从double write buffer写到真正的 segment 中的时候, 系统会自动合并连接空间刷新的方式, 每次可以刷新多个pages;