优化原理
MySQL InnoDB 的 page size 一般为 16KB,数据校验也是按 16KB 页面来计算的。但操作系统写入磁盘是以 4KB 页进行的,因此在极端场景如掉电,操作系统无法保证 InnoDB 的 16KB 页的原子写入,即 partial write。 为了解决 partial write 问题,MySQL 在将脏数据 flush 到数据文件时,会先将脏数据拷贝到 double write buffer,之后通过 double write buffer 写入到共享表空间,再调用 fsync 刷到数据文件。 因此,数据页面存在双倍的写入,这在实际应用场景可能带来如下问题: 1)云盘场景,额外占用存储带宽,抖动问题变多; 2)传统物理机场景,额外的写入会降低 SSD 的寿命(TBW 为 SSD 的生命周期重要指标之一)。 大致原理图如下:
Double Write 介绍: https://dev.mysql.com/doc/refman/8.0/en/innodb-doublewrite-buffer.html
16k 原子写方案旨在通过文件系统 COW 异地更新的机制,确保 MySQL 16k 页面原子写入,同时对 MySQL 应用无侵入,优化 MySQL 的性能和数据写入量,解决 Double Write 带来的额外带宽占用以及降低 SSD 寿命等问题。
使用方法
1、下载 OpenAnolis 社区 SIG 的特性分支代码,并编译安装。
git clone git@gitee.com:anolis/storage-cloud-kernel.git git checkout feature/atomic-write make anolis_defconfig make -j64 -s sudo make modules_install -j64 -s sudo make install sudo reboot
2、安装 MySQL 和客户端:
sudo yum install mariadb mariadb-server mariadb-devel
3、创建 xfs 数据盘并挂载,用于保存 MySQL 数据库。 (注意需确保 xfsprogs 版本支持 reflink 特性)
sudo mkfs.xfs -m reflink=1 <device> sudo mount <device> <mnt_point> sudo chown -R mysql:mysql <mnt_point>
例如:
sudo mkfs.xfs -m reflink=1 /dev/vdb sudo mount /dev/vdb /var/lib/mysql sudo chown -R mysql:mysql /var/lib/mysql
4、修改 MySQL 配置文件 /etc/my.cnf,使用 direct 写入,并关闭 double write。例如:
[mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock ... innodb_file_per_table innodb_page_size = 16384 innodb_buffer_pool_size = 12288M innodb_use_native_aio = 0 innodb_flush_method = O_DIRECT innodb_doublewrite = 0 # 已支持 16k 原子写,无需 double write
- 设置 mysql db 目录为原子写目录,如:
sudo chattr +c /var/lib/mysql
- dmesg 将显示原子写已针对目录开启信息:
[ 330.918099] XFS (vdb): atomic write set on dir ino 128
6、启动 mysqld 服务。
sudo systemctl start mariadb
7、下载并编译 sysbench。
git clone https://github.com/akopytov/sysbench.git cd sysbench ./autogen.sh ./configure make -j64 -s sudo make install
8、运行测试。
sudo ./test-mysql.sh
---------------------------------------------------------------------------------------
更多调优信息,请参考:
KeenTune SIG:https://openanolis.cn/sig/KeenTune
阿里云龙蜥操作系统专区:https://developer.aliyun.com/group/aliyun_linux