备份恢复是 DBA 必备的技能,开源数据库 MySQL 在社区中有不少常用的备份恢复方案,xtrabackup,mypump,mydumper,mysqldump,mysql enterprise backup 等等。但是这些方法多数都是从外部利用各类数据库的机制来完成备份与回复,因此多多少少会存在操作步骤多,备份恢复比较慢等问题。于是 Oracle 在 19 年 7 月下旬发布的 MySQL 的 8.0.17 版本中,加入了一个全新的功能性插件:Clone。这个插件只需要几行 client 命令就可以完成数据库的备份恢复,且花费的时间远也低于常规的备份恢复手段。
Clone 插件如字面意思一般,它的作用就是 “Clone” 一个 MySQL 实例。安装这个插件之后,可以通过 MySQL client 登录到一个空的 MySQL 实例(推荐空实例),通过 Clone 命令获取到一份远端 MySQL 实例的一致性数据镜像,且整个过程和进度可以在 information_schema 的系统表中监测到。
简单的原理图如下:
Recipient 节点就是发起 Clone 操作的空实例;Donor 节点就是目标实例,是 Clone 操作的对象。当 Clone 操作完成之后,Recipient 节点就拥有 Donor 节点完整的 InnoDB 数据。从 8.0 开始,所有的 MySQL 系统表已经全部转换为 InnoDB 引擎,所以 Clone 操作也会把用户和授权信息完整的 Clone 到 Recipient 节点。
Clone 操作的标准流程如下:
使用 Clone 插件需要注意以下几点:
由于 Clone 插件创建出来的数据库镜像的数据是符合一致性的,因此在搭建新的从库,创建临时测试库,本地、远端的一致性备份等可以直接访问源实例的场景会非常适合 Clone 插件。同时 Clone 插件也能满足 TB 级 MySQL 实例的备份需求,而 xtrabackup 和 mysqlbackup 会受到 redo log rotate 的影响,绝大多数场景下无法对 TB 级的 MySQL 进行备份,dump,快照等方式则存在磁盘空间或者时间上的缺陷。
在 MySQL Client 安装 Clone 插件(建议都装上这个插件):
INSTALL PLUGIN CLONE SONAME "mysql_clone.so";
CREATE USER clone_user IDENTIFIED BY "clone_password";
GRANT BACKUP_ADMIN ON *.* to clone_user;
授予查看 Clone 进度等相关信息的权限:
GRANT SELECT ON performance_schema.* TO clone_user;
GRANT EXECUTE ON *.* to clone_user;
##登录到Recipient的mysql client端执行
SET GLOBAL clone_valid_donor_list = 'donor.host.com:3306';
##Clone 操作推荐在shell命令行下挂到后台执行
CLONE INSTANCE FROM clone_user@donor.host.com:3306 IDENTIFIED BY "clone_password";
SELECT STATE, CAST(BEGIN_TIME AS DATETIME) as "START TIME",
CASE WHEN END_TIME IS NULL THEN
LPAD(sys.format_time(POWER(10,12) * (UNIX_TIMESTAMP(now()) - UNIX_TIMESTAMP(BEGIN_TIME))), 10, ' ')
ELSE
LPAD(sys.format_time(POWER(10,12) * (UNIX_TIMESTAMP(END_TIME) - UNIX_TIMESTAMP(BEGIN_TIME))), 10, ' ')
END as DURATION
FROM performance_schema.clone_status;
结果展示:
+-------------+---------------------+------------+
| STATE | START TIME | DURATION |
+-------------+---------------------+------------+
| In Progress | 2019-07-17 17:23:26 | 4.84 m |
+-------------+---------------------+------------+
检查 Clone 的操作进度:
SELECT STAGE, STATE, CAST(BEGIN_TIME AS TIME) as "START TIME",
CASE WHEN END_TIME IS NULL THEN
LPAD(sys.format_time(POWER(10,12) * (UNIX_TIMESTAMP(now()) - UNIX_TIMESTAMP(BEGIN_TIME))), 10, ' ')
ELSE
LPAD(sys.format_time(POWER(10,12) * (UNIX_TIMESTAMP(END_TIME) - UNIX_TIMESTAMP(BEGIN_TIME))), 10, ' ')
END as DURATION,
LPAD(CONCAT(FORMAT(ROUND(ESTIMATE/1024/1024,0), 0), " MB"), 16, ' ') as "Estimate",
CASE WHEN BEGIN_TIME IS NULL THEN LPAD('0%', 7, ' ')
WHEN ESTIMATE > 0 THEN
LPAD(CONCAT(CAST(ROUND(DATA*100/ESTIMATE, 0) AS BINARY), "%"), 7, ' ')
WHEN END_TIME IS NULL THEN LPAD('0%', 7, ' ')
ELSE LPAD('100%', 7, ' ') END as "Done(%)"
FROM performance_schema.clone_progress;
结果展示:
+-----------+-------------+------------+------------+-----------+---------+
| STAGE | STATE | START TIME | DURATION | Estimate | Done(%) |
+-----------+-------------+------------+------------+-----------+---------+
| DROP DATA | Completed | 17:23:26 | 790.86 ms | 0 MB | 100% |
| FILE COPY | In Progress | 17:23:27 | 4.85 m | 94,729 MB | 47% |
| PAGE COPY | Not Started | NULL | NULL | 0 MB | 0% |
| REDO COPY | Not Started | NULL | NULL | 0 MB | 0% |
| FILE SYNC | Not Started | NULL | NULL | 0 MB | 0% |
| RESTART | Not Started | NULL | NULL | 0 MB | 0% |
| RECOVERY | Not Started | NULL | NULL | 0 MB | 0% |
+-----------+-------------+------------+------------+-----------+---------+
重启完成 Crash Recovery 之后,整个 Clone 操作就结束了。
为了防止物理资源的限制,测试使用了两台独立的物理机,基本配置为 Intel-E5 40 核的 CPU,128GB 的内存,3TB 的 Intel SSD。数据库版本使用 MySQL 8.0.17,用 sysbench 生成了 4 张测试表,每张表约 10 亿行数据,总的数据集大小约 1TB。
测试主要对比的指标为时间,具体指从一个运行的实例上建立一个完整可用的镜像实例所花费的时间。测试的对比对象为 LVM 快照和 xtrabackup 工具。
MySQL 实例的配置使用相同的参数配置,数据目录均使用 SSD 磁盘,备份目录均使用 SAS 磁盘,redo log 为 2G 大小,总共 4 个文件。本次对比中会记录操作的各个阶段的耗时,数据仅作为实际备份恢复耗时的参考(部分数据可作为 TB 级 MySQL 实例的 RTO 的参考)。
xtrabackup 备份开启了压缩与流数据打包,备份的数据流存储到 SAS 盘,恢复过程中,整个解包和解压缩均在 SAS 盘完成。因此 Xtrabackup 的恢复备份流程总共包括以下几个步骤:打包压缩 -> 解包 -> 解压缩 -> 恢复备份 -> 本地 copy 数据文件 -> 成功启动,本次测试参考的流程为本地备份恢复。
快照完成的时间定为把完整的快照数据拷贝到 SAS 盘之后,本次测试不做实际快照备份的操作,仅以磁盘写入吞吐量的平均值来做粗略估计。快照备份的速度按照 SAS 盘的平均写入速度(200MB/s)来计算。快照恢复的速度按照 SAS 盘的平均读取速度(300MB/s)来计算。总共 1000GB 的数据量。
MySQL Clone 插件直接使用 Recipient 节点的数据目录(SSD 磁盘)为目标目录,Clone 插件的配置如下:
##设置为ON时,MySQL会忽略用户的设置,自动调整Clone的参数, 速度非常慢
##但是对服务器的CPU和IO资源几乎没有影响。
clone_autotune_concurrency = OFF
##设置传输数据时可用的buffer大小,默认大小为4MB,增加这个参数允许Clone插件更充分的利用IO设备的性能,加快Clone操作的速度。
clone_buffer_size = 268435456
##设置Clone操作尝试获取相关锁的等待时间
clone_ddl_timeout = 300
##设置Clone操作是否开启压缩功能来进行数据传输,会减少网络带宽的消耗,增加CPU的消耗
clone_enable_compression = ON
##设置Clone操作使用的并发线程数
clone_max_concurrency = 24
##设置Clone操作可使用的最大数据传输吞吐量
clone_max_data_bandwidth = 0
##设置Clone操作可使用的最大网络带宽
clone_max_network_bandwidth = 0
测试中模拟的实际业务场景分为四个:
xtrabackup 会因为 redo log 循环写入的原因导致备份失败,因此本次测试中不对高写入负载的场景进行测试,需要 Xtrabackup 支持 8.0.17 的 redo log archives 特性之后才能解决此类问题。
测试场景的几种负载由 sysbench 的脚本来进行模拟,对应的并发压力为:
实测过程中,Clone 插件对 donor 实例的主要压力在于 CPU,以及 IO 设备的读取性能上,对写入性能的影响相对比较小,即使达到中等量级的写入压力,Clone 的过程中也只达到了约 8% 的写入性能损失,但是在标准的读写负载场景下,性能损失达到了约 28%,主要是因为 CPU 的资源发生了争抢。
虽然在规划中没有加入高写入负载的测试,但是实际发现即使 sysbench 的写入并发设置为 1(写入 QPS 约 4000),xtrabackup 依旧不能完成备份操作(由于 redo log 的循环写入),因此实际测试的结果中,xtrabackup 仅有无负载的测试数据。
横向对比几种不同的备份恢复方案(所有图例的 None 字段代表负载):
从图中可以看到 Clone 插件花费的时间仅有快照的 40%,Xtrabackup 的 18%,这是因为 Clone 的过程几乎就是从远端实例把数据 rsync 到本地的 SSD 磁盘,整个过程没有 SAS 盘的参与。
纵向对比 Clone 插件在不同场景下的表现:
可以看到随着写入负载,或者是读写负载的增加,Clone 插件的耗时也会增长,增加的幅度最多达到了 50%,因此 Clone 操作最好在业务比较少的时候进行,或者是在其他空闲 MySQL 实例进行。
MySQL 8 还在随着版本不断地添加新功能,慢慢的,也许高 QPS,高并发,微秒级查询等 MySQL 的短板在未来会慢慢的都补上,是时候拥抱新技术带来的效率提升与改变了。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。