Xtrabackup 2.2.12 线上使用过程中遇到的 FTWRL 问题

在使用Xtrabackup 2.2.12进行线上MySQL热备份时遇到FTWRL锁问题,导致从库SQL线程堵塞长达7小时。问题源于不同备份端口在相同tmpdir下创建的suspended文件冲突。解决方案包括设置不同的tmpdir,修改文件名,或升级到更高版本的Xtrabackup。

背景

最近线上使用 Xtrabackup 做热备份的时候遇到一个非常奇怪的问题: 线上在从库上进行热备的时候,从库的 SQL 线程堵在了 waiting for global read lock 上,时间最长的堵了 7 小时。

原理

在摆开问题之前先来看下 Xtrabackup 2.2.12 备份的原理。

xtrabackup 2.3 之前有两个程序:一个是 innobackupex perl 脚本,一个是 xtrabackup c 程序。xtrabackup 负责拷贝跟 innodb 相关的文件,innobackupex 主要负责拷贝非 innodb 文件,两个程序通过创建和删除中间文件来同步,以便能做到一个最终一致的备份。两个程序使用创建和删除文件方式进行同步的过程如下:

  • xtrabackup 创建 xtrabackup_suspended_1, innobackupex 删除该文件。该文件和增量备份逻辑有关,这里不分析。
  • xtrabackup 创建 xtrabackup_suspended_2, 表示跟 innodb 相关的文件(增量 redo,idb 文件,ibdata1)都已拷贝完成并阻塞,这时候 innobackupex 如果检测到该文件存在则往里面写入 xtrabackup 的 pid,接着进行下一步的 FTWRL 操作,进而开始拷贝 non-innodb 文件。
  • innobackupex 拷贝完 non-innodb 文件,并记录 binlog 信息后就简单的将文件 xtrabackup_suspended_2 删除(unlink),innobackupex 接着进入阻塞状态。xtrabackup 检测到该文件被删除后就继续开始拷贝增量日志信息(redolog)。
  • xtrabackup 拷贝完所有增量日志后(LSN 不再变化,因为加了 FTWRL 锁以后正常 LSN 就不会再增加了)会创建 xtrabackup_log_copied 文件,innobackupex 检测到文件创建后先将 xtrabackup_log_copied 删除,然后释放全局读锁,接着有需要的话 start slave sql_thread,最后等待 xtrabackup 进程结束。到这里整个备份基本结束了。
  • xtrabackup 检测到 xtrabackup_log_copied 被删除后自己释放资源并结束,innobackupex 发现子进程结束后再接着做其它后续工作。

一些细节

innobackupex 脚本在调用 xtrabackup 进行流式备份(tar)的时候会将 xtrabackup_logfile 和 xtrabackup_suspended 文件创建在 tmpdir 目录中(非流式备份会将 suspended 文件拷贝至备份目录,因为一般备份目录不同端口都不同,所以不会有问题),xtrabackup_logfile 文件会等日志(redo)拷贝完成后再传到远程,而 xtrabackup_suspended 文件则是中间生成的同步文件。

问题回顾

观察线上的备份日志,可以看到晚上 8:09 分开始加全局读锁准备拷贝非 InnoDB 文件,按照之前的原理分析,正常情况下后面不会再有拷贝 idb 文件的情况,但是却发生了。

1

可以看到用了 20 秒的时间把所有的非 InnoDB 表备份走了,但没有释放全局读锁。其实 20 秒的时间影响也比较大了,在主库上备份更需要慎重考虑。

2

两个小时后备份结束了,并释放了全局读锁。

3

这种情况有悖于该工具所描述的 “不影响线上服务” 的宗旨。于是决定去看下到底是什么原因。

线上的一些环境

在描述之前补充下当时备份的一些环境

  • Xtrabackup 版本是 2.2.12
  • MySQL 版本是 5.5,tmpdir 用的配置文件中指定的,路径一样
  • 备份方式是 xtrabackup + tar 压缩的全量备份
  • 出现备份问题的都是用的上面的备份方式
  • 出现备份问题的机器上使用流式备份的端口至少 2 个

思路

先整理了下线上的一些环境和问题的共性,接着开始排查。排除了新旧备份的使用上的区别,无果。不甘心去看了代码,整理了下拷贝 idb 文件、非 innodb 文件和加全局读锁的顺序。结合之前的原理分析,再考虑线上环境,怀疑在拷贝完 innodb 文件之前,应该是有别的进程创建了 suspended 文件,导致出现问题,正好同一机器上的备份端口不止一个,并且创建的 suspended 文件都在同一目录下,而且中间文件的文件名都一样。如果两个端口同时开始备份,数据量小的端口先创建了 suspended 文件,那么另一个数据量大的端口就会出现开头所描述的问题。经测试后重现。

解决办法

  • 加上 tmpdir 参数,指定不同的目录(这个代价比较小)
  • xtrabackup 创建的文件名需要改下,innobackupex 脚本也得改下,使得每个备份进程创建的中间文件名都不一样,比如加上 xtrabackup 进程的 id
  • 直接上 xtrabackup 2.3 或者最新版(2.2 是当时上的时候的最新版本),因为 2.3 以后的版本程序 Percona 全部用 c 重写了

总结

该问题出现需要满足的三个条件

  • 同一机器上有至少 2 个端口在备份
  • 使用流式备份
  • suspended 中间文件的创建路径相同
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值