摘要:本文来自华为云MySQL研发团队,主要分享了MySQL备份工具Xtrabackup的备份过程、华为云数据库团队对其做的优化改进,以及在使用中可能遇到的问题与解决方法。

本文分享自华为云社区《华为云带你探秘Xtrabackup备份原理和常见问题分析》,作者:GaussDB 数据库 。

本文来自华为云MySQL研发团队,主要分享了MySQL备份工具Xtrabackup的备份过程、华为云数据库团队对其做的优化改进,以及在使用中可能遇到的问题与解决方法。文章讨论的内容主要是针对华为云RDS for MySQL, 以及用户自建的社区版MySQL数据库,希望有助于大家理解和使用Xtrabackup,以后面对Xtrabackup问题也更加从容。

一、Xtrabackup简介

Xtrabackup是Percona团队开发的用于MySQL数据库物理热备份的开源备份工具,具有备份速度快、支持备份数据压缩、自动校验备份数据、支持流式输出、备份过程中几乎不影响业务等特点,是目前各个云厂商普遍使用的MySQL备份工具。

当前Xtrabackup存在两个版本:Xtrabackup 2.4.x与8.0.x,分别用于备份MySQL 5.x与MySQL 8.0.x 版本。下面我们分别介绍 Xtrabackup如何备份MySQL社区版以及华为云上的Xtrabackup的备份原理

二、社区版MySQL的Xtrabackup备份

Xtrabackup是为Percona MySQL设计的,同时也支持对官方社区版本MySQL进行备份,过程如下图所示:
image.png

图1:Xtrabackup备份官方MySQL流程示意

  1. 兼容性检查:Xtrabackup社区版本只支持 MyISAM , InnoDB , CSV , MRG_MYISAM 四种存储引擎的表,其他存储引擎的表不会备份;在这一步中,通过查询tables,若发现存在表的存储引擎不是上述四种引擎之一,会打印warning, 表明Xtrabackup不会备份该表。
  2. 启动redo后台备份线程:启动redo后台备份线程,从备份实例的最近一次checkpoint LSN的位置开始备份所有增量的redo log,一直持续到备份任务结束。
  3. 加载所有的innodb表空间:打开并扫描所有innodb表的数据文件,检查所有表空间的第一个页面,初始化所有表的内存结构。
  4. 备份innodb表:遍历步骤3所构建的表的内存结构,备份每一个innodb表的数据文件,备份的过程中会检查每个页面的数据是否正确。
  5. 加备份锁 FLUSH TABLES WITH READ LOCK (FTWRL):FTWRL锁是MySQL实例级的读锁,加锁过程复杂,且加锁之后,所有表的所有更新操作以及DDL都会堵塞。
  6. 备份非innodb表:因为在步骤5我们已经对实例加了读锁,因此,此时备份非innodb表是安全的,此时一定没有写业务。
  7. 记录binlog当前的GTID信息:请注意,此时我们仍持有全局读锁。这一步主要是方便我们使用该备份集快速地创建出备机。
  8. 停止redo备份线程。
  9. 释放锁资源,备份结束。

需要注意的是,Xtrabackup 2.4.x与8.0.x在第7、8这两个步骤存在差异,这个差异有MySQL 8.0.x的原因,详情我们在下文介绍。

三、华为云RDS for MySQL备份

在备份社区版MySQL实例时,Xtrabackup会对实例加全局读锁(FTWRL),该锁对数据库的业务影响很大,严重时甚至会导致数据库“挂起”,这对客户来说是不可接受的。因此华为云MySQL团队对这个过程进行了优化,主要有两点:

  1. 对MySQL 5.x以及0.x增加了备份锁:LOCK TABLES FOR BACKUP
  2. 对MySQL 5.x新增了binlog锁:LOCK BINLOG FOR BACKUP

优化之后,华为云Xtrabackup对MySQL的备份过程如下:
image.png

图2 Xtrabackup备份华为云MySQL流程示意

与FTWRL锁相比,备份锁 LOCK TABLES FOR BACKUP对客户实例影响很小,其加锁过程简单,加锁期间innodb表的DML操作不受影响,但是非innodb表的所有的更新操作以及DDL操作仍然是不允许的。

备份完所有的表文件后,Xtrabackup需要获取binlog GTID信息。

• 对于MySQL 5.x版本,Xtrabackup 2.4.x会执行 LOCK BINLOG FOR BACKUP 操作,对binlog加锁,然后获取GTID信息。
• 对于MySQL 8.0.x版本,华为云Xtrabackup 8.0.x沿用官方的一致性备份点查询方法。Xtrabackup查询log_status 时,MySQL服务器会分别对redo log, binlog等加轻量级锁,获取一致性备份点,这个过程是非常短暂的,对实例的运行几乎没有影响。MySQL 8.0.x的备份一致性点,会告诉我们一致性的redo log LSN以及binlog的GTID;查询完备份一致点后,Xtrabackup会备份最后一个binlog文件,用于恢复时仲裁事务是否需要回滚;最后,redo log备份线程任务会在其读取到的redo log的LSN大于查询到的备份一致性点的redo log LSN处停止。

由于Xtrabackup 2.4.x与8.0.x在处理binlog时存在差异,恢复过程也存在差异,我们会在后续文章中详细阐述。

四、常见问题与解决方法

华为云已经使用Xtrabackup为公司几乎所有的MySQL实例提供备份服务,在使用过程中,我们积极与社区保持联系,向Percona社区报告使用过程中的一些问题,帮助Xtrabackup向更好的方向演进。此外,对于发现的一些致命问题,若社区未能及时修复,华为云数据库团队会进行及时修复以保证备份数据的正确性。

下面是我们总结在使用Xtrabackup备份过程各个阶段可能遇到的问题,分析其原因以及对应的解决方法,

1. 兼容性检查阶段

  • 问题现象:Xtrabackup启动后,立即长时间“挂起”,查看日志发现redo log备份线程也没有启动。

原因:Xtrabackup兼容性检查时无法获取MDL锁。Xtrabackup兼容性检查是通过查询 imformation_schema.tables这个插件表实现:

“SELECT CONCAT(table_schema, '/', table_name), engine FROM information_schema.tables WHERE engine NOT IN ('MyISAM', 'InnoDB', 'CSV', 'MRG_MYISAM') AND table_schema NOT IN ('performance_schema', 'information_schema', 'mysql')”

在查询每张表时,需要获取对应表的MDL锁,如果此时MySQL实例中存在长时间的DML或者DDL 语句,或者更严重者出现了MDL死锁,上面的查询会一直堵塞在等待MDL锁阶段,此时 Xtrabackup会长时间“挂起”。

解决办法:若等待锁的原因只是因为其他SQL语句的堵塞,等待其他SQL执行完成即可;若是发生了死锁,此时需要分析出死锁原因,将死锁解除;华为云RDS for MySQL提供了MDL锁视图功能,可以很好地帮助用户分析业务的MDL死锁。

2.redo log备份阶段

  • 问题现象1:redo log回卷,备份失败,Xtrabackup报如下错误信息:
    “xtrabackup: error:it looks like InnoDB log has wrapped around before xtrabackup could process all records due to either log copying being too slow, or log files being too small.\n");”

原因:在备份的过程中,如果主机业务负载很高,导致redo log写入的速度很快,会发生Xtrabackup的redo log备份线程的备份速度小于redo log的写入速度,因为MySQL redo log文件写入使用了 round-robin的方式,使得新写入的日志覆盖了之前写入却还未备份的日志,因此备份失败。

解决办法:推荐在业务低峰期进行备份,或者增大redo log的文件大小。

  • 问题现象2:备份因DDL操作失败,错误信息如下:

“An optimized (without redo logging) DDLoperation has been performed. All modified pages may not have been flushed to the disk yet.

PXB will not be able take a consistent backup. Retry the backup operation”

原因: 备份过程中MySQL实例发生了创建索引的DDL操作,因为创建索引不会写redo,若继续备份会引起数据不一致问题,所以Xtrabackup在这种场景中备份失败是预期行为。

解决办法:不要在备份过程中创建索引,如果确实需要,建议在建表语句中直接带上索引,或者使用 lock-ddl 参数进行备份(阻塞实例上新的DDL操作)。

  • 问题现象3:undo truncate导致备份失败,Xtrabackup错误信息如下:

“An undo ddl truncation (could be automatic) operation has been performed.”

原因:在Xtrabackup备份期间,如果MySQL实例发生undo truncate时,有可能会出现写入新 undo文件(space id不同)的undo日志丢失导致恢复出来的数据存在问题。官方在Xtrabackup 8.0.14版本(基于MySQL 8.0.21)对该问题进行了修复,修复方法是redo备份线程,解析redo log时若发现该操作是undo log的truncate操作,则会备份失败。遗憾的是,该修复并没有完全解决问题,在以下两种场景中,社区版本的Xtrabackup仍可能会发生恢复出来的数据存在不一致的现象:

  1. MySQL版本低于MySQL 8.0.21;
  2. 用户在备份过程中,自己创建了新的undo tablespace。

解决办法:在备份期间关闭undo tablespace的truncate操作,并禁止用户创建undo tablespace, 能够有效地防止备份数据恢复出来不一致的问题;另外华为云Xtrabackup对这个问题进行了进一步的修复,可以有效地防止此类现象发生。

3.加载表空间阶段

  • 问题现象1:Xtrabackup报错:Too many open files

原因:操作系统允许同时打开的文件数量是有限的,Xtrabackup在load tablespace阶段会同时打开所有的表文件,如果Xtrabackup打开的表的个数超过了该限制,则会备份失败。

解决办法:调大操作系统,允许同时打开最大文件数的配置,或者使用 lock-ddl 参数(阻塞实例上新的DDL操作)。

  • 问题现象2:rename table导致备份失败,错误信息如下:

“Trying to add tablespace 'xxxx' with id xxx to the tablespace memory cache, but tablespace xxxx already exists in the cache!;”

原因:在Xtrabackup打开表空间的全过程是没有加锁的,如果发生了rename table有概率会发生重复加载相同的表空间,此时Xtrabackup会检测到重复的tablespace id,因此备份失败。

解决办法:一般来说,加载表空间是一个很快的操作,rename table并不是一个很频繁的操作,这种情况重试即可(Percona Xtrabackup 2.4.x仅支持单线程加载表空间,华为云Xtrabackup支持多线程加载表空间)。

4.备份innodb表阶段

  • 问题现象:innodb表数据文件损坏,备份失败,错误信息如下:

“xtrabackup: Database page corruption detected at page xxxx, retrying.”

原因:Xtrabackup在备份innodb表数据文件时,会检查每个页面的checksum,如果发现checksum不对,则备份失败,这时说明MySQL实例的数据已经发生了损坏(例如磁盘静默错误)。

解决办法:需要通过恢复前一次的备份数据或者其他的办法将数据进行修复之后,备份才能成功,在后续的文章中,我们也会详细介绍数据修复办法。

五、结语

本文主要对比介绍了Xtrabackup备份原理,备份社区版MySQL以及华为云对其的改进,并分享了Xtrabackup常见问题的排查与解决,后续我们也会为大家带来更深入的分析,更实用的使用技巧,希望对大家理解和使用Xtrabackup有帮助。我们也将持续为客户提供更好的数据库服务,并时刻守护客户的数据安全。

最后,告诉大家一个好消息,云数据库MySQL包年19.9元起,助力企业无忧上云,欢迎大家前来体验

点击关注,第一时间了解华为云新鲜技术~


华为云开发者联盟
1.4k 声望1.8k 粉丝

生于云,长于云,让开发者成为决定性力量