• 进入"运维那点事"后,希望您第一件事就是阅读“关于”栏目,仔细阅读“关于Ctrl+c问题”,不希望误会!

MySQL备份恢复:Xtrabackup原理阐述

MySQL 彭东稳 8年前 (2016-04-12) 31446次浏览 已收录 0个评论

一、Xtrabackup介绍

Percona XtraBackup(简称 PXB)是 Percona 公司开发的一个用于 MySQL 数据库物理热备的备份工具,支持 MySQL(Oracle)、Percona Server和 MariaDB,并且全部开源,真可谓是业界良心。据官方介绍,这也是世界上唯一一款开源的能够对Innodb和Xtradb存储引擎进行物理热备的工具。XtraBackup 包含两部分:xtrabackup 的 c 程序和 innobackupex 的 Perl 脚本;前者主要用于处理 InnoDB 表的备份;后者是前者的封装,主要包括一些与 MySQL 服务器的通信和 MyISAM 表的备份。

特点(官方):

  1. 备份过程快速可靠
  2. 备份过程不会打断正在执行的事务
  3. 能够基于压缩等功能节约磁盘空间和流量
  4. 自动实现备份检验
  5. 还原速度快

二、Xtrabackup工具集

软件包安装完后一共有 4 个可执行文件,如下:

其中最主要的是 innobackupex 和 xtrabackup,前者是一个 perl 脚本,后者是 C/C++ 编译的二进制程序。

xtrabackup 是用来备份 InnoDB 表的,不能备份非 InnoDB 表,和 mysqld server 没有交互;innobackupex 脚本用来备份非 InnoDB 表,同时会调用 xtrabackup 命令来备份 InnoDB 表,还会和 mysqld server 发送命令进行交互,如加全局读锁(FTWRL)、获取位点(SHOW SLAVE STATUS)等。简单来说,innobackupex 在 xtrabackup 之上做了一层封装。

一般情况下,我们是希望能备份 MyISAM 表的,虽然我们可能自己不用 MyISAM 表,但是 mysql 库下的系统表是 MyISAM 的(MySQL 8.0 已经全部替换为 InnoDB 表),因此备份基本都通过 innobackupex 命令进行;另外一个原因是我们可能需要保存位点信息。

另外 2 个工具相对小众些,xbcrypt 是加解密用的;xbstream 类似于 tar,是 Percona 自己实现的一种支持并发写的流文件格式。两都在备份和解压时都会用到(如果备份用了加密和并发)。

本文介绍的主角是 innobackupex 和 xtrabackup。如果你想要一个可用的完整备份,请使用 innobackupex,因为 xtrabackup 本身不会复制表定义,触发器或其他任何不是 .ibd 的文件。

三、Xtrabackup工作原理

首先看通信方式,innobackupex 和 xtrabackup 这 2 个工具之间的交互和协调是通过控制文件的创建和删除来实现的,主要文件有:xtrabackup_suspended_1、xtrabackup_suspended_2、xtrabackup_log_copied。

举个例子,我们来看备份时 xtrabackup_suspended_2 文件是怎么来协调 2 个工具进程的。

1. innobackupex 在启动 xtrabackup 进程后,会一直等 xtrabackup 备份完 InnoDB 文件,方式就是等待 xtrabackup_suspended_2 这个文件被创建出来;

2. xtrabackup 在备完 InnoDB 数据后,就在指定目录下创建出这个文件,然后等这个文件被 innobackupex 删除;

3. innobackupex 检测到文件 xtrabackup_suspended_2 被创建出来后,就继续往下走;

4. innobackupex 在备份完非 InnoDB 表后,删除 xtrabackup_suspended_2 这个文件,这样就通知 xtrabackup 可以继续了,然后等 xtrabackup_log_copied 被创建;

5. xtrabackup 检测到 xtrabackup_suspended_2 文件删除后,就可以继续往下了。

是不是感觉有点不可思议,通过文件是否存在来控制进程,这种方式非常的不靠谱,因为非常容易被外部干扰。比如文件被别人误删掉,或者 2 个正在跑的备份控制文件误放在同一个目录下,就等着备份乱掉吧,但是 Percona 就是这么干的。之所以这么搞,估计主要是因为 Perl 和 C 二进制程序 2 个进程,没有既好用又方便的通信方式,搞个协议啥的太麻烦了。但是官方也觉得这种方式不靠谱,2011 年就搞了个 blueprint 要用 C 重写 innobackupex,终于在 2.3版本 实现了。

现在 innobackupex 功能全部集成到 xtrabackup 里面,只有一个二进制文件,另外为了使用上的兼容考虑,innobackupex 作为 xtrabackup 的一个软链存在,也就是说 innobackupex 在后面版本即将会移除。

对于二次开发来说,2.3 版本摆脱了之前 2 个进程协作的负担,架构上明显要好于之前版本。考虑到 Perl + C 这种架构的长期存在,大多数读者朋友也基本用的 2.3 之前版本,本文的介绍也是基于老的架构(2.2 版本),但是原理和 2.3 版本是一样的,只是实现上的差别。

另外 xtrabackup 能够实现针对 InnoDB 表的无锁备份,即所有的读写请求、DDL 语句在整个备份过程中都是不受影响的。它的实现是基于 InnoDB 对事务的支持,利用其崩溃恢复的功能来实现的。MySQL 所有的更新操作都是在内存中完成的,然后异步的刷入磁盘进行持久化。支持事务的存储引擎,为了保证 MySQL 宕机后内存中还未刷盘的更新不会丢失,设计了事务引擎日志(redo log)。并且 InnoDB 每个 page 有个 LSN 号,LSN 是全局递增的,page 被更改时会记录当前的 LSN 号,page中的 LSN 越大,说明当前 page 越新(最近被更新)。

redo log 会记录 InnoDB 数据表每个 page 的修改记录,然后记录日志序号(LSN),异步线程在将脏页刷新到磁盘的同时,维护一个检查点 LSN,两个 LSN 之间的差异就是数据宕机后丢失的更新。在数据库启动时,只要事务日志保存完好,就可以根据 redo log 和 undo log 将数据库恢复到崩溃前的一致性状态。主要就是应用(前滚)已经提交的事务日志到数据文件,并将修改过但没有提交的数据进行回滚操作。当然,这是在没有开启 binlog 的前提下,有 binlog 时就更加复杂,不在这里讨论了。

通过在 MySQL 执行 show engine innodb status,我们可以清楚的看到:

Log sequence number

表明当前 redo log 的最新 LSN,创建一条 Redo 日志,此时在 Buffer Poll 中。

Log flushed up to

表明记录日志持久化到磁盘上的重做日志文件的 LSN。

Pages flushed up to

脏页数据刷新到磁盘数据文件时最新的 LSN(也就是 NEWEST_MODIFICATION)。

Last checkpoint at

最后一次检查点对应的 LSN,脏页数据刷新到磁盘数据文件时最老的 LSN(也就是 OLDEST_MODIFICATION),checkpoint LSN 就是记录此 OLDEST_MODIFICATION 值。此检查点之前的脏数据都已经刷新到磁盘,同时也是崩溃恢复时指定的起点。

xtrabackup 备份时,首先会模拟 MySQL 实例的方式以读写模式打开 redo 文件(ib_logfile0 文件),然后读取文件头的 checkpoint LSN。我们知道 checkpoint LSN 表示小于或等于该 LSN 的数据都已经刷新到磁盘了。然后 xtrabackup 会 fork 出一个线程从该 checkpoint LSN 位置开始拷贝 redo log 到 xtrabackup_logfile 文件,同时不断扫描 redo log,当有新产生的 redo log 时就拷贝到 xtrabackup_logfile 文件。

记录了 checkpoint LSN 后,xtrabackup 就找到了一个数据一致点,然后直接拷贝 ibd 数据文件即可。在进行恢复时,即从该 LSN 作为起点,大于该 LSN 的 redo log 都需要重做或者回滚,保证数据一致性。

从前面我们对数据库备份过程上锁的必要性的分析可知,除了解决数据文件的一致性外,还需要解决 DDL 和获取 Binlog 的问题。而该问题就需要依赖对数据库加锁来完成,首先当 xtrabackup 拷贝数据文件的线程完成后,会通知 xtrabackup 主线程,然后主线程会连接上 MySQL 执行 flush table with read lock,该操作会锁定整个实例的所有带 X 锁的读,更新、插入、删除和 DDL 语句,相当于冻结了 LSN。接着开始拷贝 MySQL 的 MyISAM 表文件(MyISAM 文件拷贝多久,整个数据库就锁多久),此时不断扫描 redo log 的线程还在工作,但 MySQL 当前 LSN 不会再推进了,拷贝完 MyISAM 文件后,同时会 fsync 一次 redo log 信息(这个操作很重要)。然后拷贝 redo log 线程完成结束,接着 xtrabackup 记录 LSN,此为最终 LSN;并记录当前 Binlog 的文件名和位置;最后 unlock tables 释放锁,这样就完成了一次完整的备份过程。

四、Xtrabackup备份过程

xtrabackup 整个详细备份过程如下图(基于 2.4 版本画的):

MySQL备份恢复:Xtrabackup原理阐述

1. xtrabackup 在启动后,首先会读取 MySQL 配置文件,找到数据目录和日志文件位置。

2. 创建 xtrabackup_logfile 文件,模拟 MySQL 实例,以读写模式打开并读取 redo log 文件,获取当前 checkpoint LSN。

3. 然后 xtrabackup fork 出一个线程从当前 checkpoint LSN 开始拷贝 redo log 到 xtrabackup_logfile。同时持续扫描 redo log 文件,有新的 redo log 产生就拷贝到 xtrabackup_logfile 文件中。然后会 fork 另一个线程拷贝 ibd 数据文件,在拷贝 ibd 文件的过程中,xtrabackup 主进程一直会处于等待状态。

4. xtrabackup 拷贝 idb 数据文件的线程完成后,通知 xtrabackup 主进程,然后线程退出。此时拷贝 redo log 的线程还在继续工作。

5. xtrabackup 收到 xtrabackup 通知后,执行 FLUSH NO_WRITE_TO_BINLOG TABLES & FLUSH TABLES WITH READ LOCK,然后获取 binlog 位点信息写入 xtrabackup_binlog_info 文件,然后开始备份非 InnoDB 文件(包括 frm、MYD、MYI、CSV、opt、par 等)。拷贝非 InnoDB 文件过程中,因为数据库处于全局只读状态,如果在业务的主库备份的话,要特别小心,非 InnoDB 表(主要是 MyISAM)比较多的话整库只读时间就会比较长,这个影响一定要评估到。

查看 general log 记录的 Server 端 xtrabackup 产生的语句:

MySQL备份恢复:Xtrabackup原理阐述

从上面的记录中可以看到,与 mysqldump 相比,xtrabackup 备份时对数据库的操作多了一个 FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS,用来调用 fsync 持久化 redo log,把与 binlog pos 位置点一致的且是最后一部分 redo log buffer 落盘,外加 NO_WRITE_TO_BINLOG 表示 FLUSH 不记录 binlog 日志中。稍后对这句的作用进行解释。

另外由于 xtrabackup 是物理拷贝文件,数据并不像 mysqldump 那样通过对数据库表执行 select 语句查询进行备份,而是通过拷贝磁盘文件进行备份的,所以,主体的备份流程还需要看 xtrabackup 的 strace 调用栈。

6. 当 xtrabackup 主进行在 MySQL 服务端做完 FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS 后,会再次读取 redo log 文件头部,获取最新 checkpoint LSN。然后 redo log 拷贝线程拷贝完最后这部分 redo log 后,就会通知主线程,然后退出。

7. xtrabackup 收到 redo log 拷贝线程通知后,就进行 UNLOCK TABLES 操作,释放全局锁。

8. 复制 buffer pool dump 文件。

9. 最后 xtrabackup 进程完成收尾工作,如资源的释放、写备份元数据信息等。至此,备份完成。

在 general_log 输出重点语句中,FLUSH NO_WRITE_TO_BINLOG TABLES、FLUSH TABLES WITH READ LOCK、SHOW MASTER STATUS、UNLOCK TABLES 几个语句的作用与 mysqldump 备份过程中的这几个语句的作用一样。而 xtrabackup 中 FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS 这句的作用是在所有的事务表和非事务表备份完成,获取了全局读锁,且使用 SHOW MASTER STATUS 语句获取了 binlog pos 之后,执行刷新 redo log buffer 中的日志到磁盘中,然后 redo log copy 线程拷贝这最后的 redo log 日志数据(为什么说是最后的 redo log 日志数据呢?因为此时使用 FLUSH TABLES WITH READ LOCK 加锁之后,使用 UNLOCK TABLES 释放全局读锁之前,不会再有新的请求进来,),拷贝完成之后就停止 copy 线程并关闭 xtrabackup_logfile 文件。然后再使用 UNLOCK TABLES 释放全局读锁。如果没有 FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS 这个动作,那么我们恢复过来的数据很有可能是缺少的,因为缺少了事务 commit 信息。这里就要明白 MySQL 是利用两阶段提交协议保证主从安全的,把事务提交分为了 prepare & commit 两个阶段。简单来说就是 MySQL 自身数据恢复需要依靠 redo 及 binlog 两者来判断事务是提交还是回滚。而 xtrabackup 并且有拷贝 binlog 文件,所以它只能依靠 redo 信息来进行数据恢复。关于两阶段提交,以及 redo 与 binlog 的关系还是先看看相关文章,不然这里其实不太好理解。

在上面描述的文件拷贝,都是备份进程直接通过操作系统读取数据文件的,只在执行 SQL 命令时和数据库有交互,基本不影响数据库的运行,在备份非 InnoDB 时会有一段时间只读(如果没有 MyISAM 表的话,只读时间在几秒左右),在备份 InnoDB 数据文件时,对数据库完全没有影响,是真正的热备。

InnoDB 和非 InnoDB 文件的备份都是通过拷贝文件来做的,但是实现的方式不同,前者是以 page 为粒度做的,后者是 cp 或者 tar 命令,xtrabackup 在读取每个 page 时会校验 checksum 值,保证数据块是一致的,而在 cp MyISAM 文件时已经做了 flush(FTWRL),磁盘上的文件也是完整的,所以最终备份集里的数据文件都是写入完整的。

上面就是 xtrabackup 的备份过程,接下来是准备(prepare)过程。在这个过程中,xtrabackup 使用之前复制的事务日志,对各个数据文件执行灾难恢复(就像 MySQL 刚启动时要做的一样)。当这个过程结束后,数据库就可以做恢复还原了。

备份 MyISAM 和 InnoDB 表最终会处于一致,在准备(prepare)过程结束后,InnoDB 表数据已经前滚到整个备份结束的点,而不是回滚到 xtrabackup 刚开始时的点。这个时间点与执行 FLUSH TABLES WITH READ LOCK 的时间点相同,所以 MyISAM 表数据与 InnoDB 表数据是同步的。类似 Oracle 的,InnoDB 的 prepare 过程可以称为 recover(恢复),MyISAM 的数据复制过程可以称为 restore(还原)。

xtrabackup 还提供了许多前文没有提到的功能特点。手册上有对各个功能都有详细的介绍。简单介绍下,这些工具提供了如流(streaming)备份,增量(incremental)备份等,通过复制数据文件,复制日志文件和提交日志到数据文件(前滚)实现了各种复合备份方式。

五、FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS的重要性

FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS 这个细节非常关键,因为不执行该操作可能会导致备份丢失一部分的数据,然后再进行主从复制的话,同步可能报错。如果要分析原因,还是得从下面的事务提交过程图来看:

MySQL备份恢复:Xtrabackup原理阐述

在上图显示的事务提交过程中,1 这个步骤会进行一次 fsync,确保日志落盘。但是从 MySQL 5.6 版本开始,已经不再需要 2 这个步骤执行 fsync 了,少了这样的 I/O 操作可以提升数据库的性能,而这对数据一致性是没有影响的,因此已经写入到二进制日志的事务在恢复的过程中一定是提交的。然而,问题在于 Xtrabackup 并不拷贝二进制日志。那么就有可能在恢复过程中存在下面的这种情况:

MySQL备份恢复:Xtrabackup原理阐述

也就是说如果 Xtrabackup 备份的时候没有备份上图左边的最后一个 InnoDB 的 commit log,这个事务在恢复的过程中就会丢失,简单来说就是数据丢失。Xtrabackup 2.2.3 版本修复了此问题,具体就是添加了 FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS 命令,在 redo log 拷贝结束前 fsync redo 到磁盘,具体可见:https://launchpad.net/percona-xtrabackup/2.2/2.2.3-ga

六、Xtrabackup恢复过程

如果看恢复备份集的日志,会发现和 mysqld 启动时非常相似,其实备份集的恢复就是类似 mysqld crash 后,做一次 crash recover。在 InnoDB 表的备份或者更直接的说 ibd 数据文件复制的过程中,数据库处于不一致的状态,所以要将 xtraback_logfile 中尚未提交的事务进行回滚,以及将已经提交的事务进行前滚,使各个数据文件处于一个一致性状态,这个过程叫做“准备(prepare)”。另外在 prepare 过程中可以使用参数--use-memory增大使用系统内存量从而提高恢复速度。

恢复的目的是把备份集中的数据恢复到一个一致性位点,所谓一致就是指原数据库某一时间点各引擎数据的状态,比如 MyISAM 中的数据对应的是 15:00 时间点的,InnoDB 中的数据对应的是 15:20 的,这种状态的数据就是不一致的。PXB 备份集对应的一致点,就是备份时 FTWRL 的时间点,恢复出来的数据,就对应原数据库 FTWRL 时的状态。

因为在 FTWRL 后,数据库是处于只读的,非 InnoDB 数据是在持有全局读锁情况下拷贝的,所以非 InnoDB 数据本身就对应 FTWRL 时间点;InnoDB 的 ibd 文件拷贝是在 FTWRL 前做的,拷贝出来的不同 ibd 文件最后更新时间点是不一样的,这种状态的 ibd 文件是不能直接用的,但是 redo log 是从备份开始一直持续拷贝的,最后的 redo 日志点是在持有 FTWRL 后取得的,所以最终通过 redo 应用后的 ibd 数据时间点也是和 FTWRL 一致的。

所以恢复过程只涉及 InnoDB 文件的恢复,非 InnoDB 数据是不动的。备份恢复完成后,就可以把数据文件拷贝到对应的目录,然后通过 mysqld 来启动了。

对于增量备份的恢复过程,与完全备份集的恢复类似,只是有少许不同:

  • 恢复过程需要使用完全备份集和各个增量备份集,各个备份集的恢复与前面说的一样(前滚和回滚),之后各个增量备份集的 redo log 都会应用到完全备份集中。
  • 对于完全备份集之后产生的新表,要有特殊处理方式,以便恢复后不丢表。
  • 要以完全备份集为基础,然后按顺序应用各个增量备份集。

七、Xtrabackup增量备份

xtrabackup 和 innobackupex 工具支持增量备份,但是只能对 InnoDB 存储引擎做增量,增量备份过程和全量备份一样,只是在 ibd 文件拷贝上有不同。MyISAM 是没有增量的机制的,每次增量备份都是全部拷贝的。支持增量备份,这意味着它可以复制自上次完全备份后更改的数据,你可以在每次完整备份之间执行多次增量备份,因此你可以设置备份计划,例如每周一次完整备份和每天增量备份,或者每天完整备份和每小时增量备份等。

增量备份可以工作,因为每个 InnoDB 页面(通常大小为 16kb)都包含日志序列号(LSN),LSN 是全局递增的,页面被更改时会记录当前的 LSN 号,页面中的 LSN 越大,说明当前页面越新(最近被更新)。增量备份就是只拷贝 LSN 大于上次完整备份或增量备份的页面,比上次备份小的页面则跳过,每个 ibd 文件最终备份出来的是增量 delta 文件,都是以 .delta 结尾。

有两种算法用于查找要复制的这类页面的集合,第一种可用于所有 MySQL 服务器类型和版本,就是通过读取所有数据页直接检查页面 LSN。Percona Server 提供的第二种方法是启用服务器上已更改的页面跟踪功能,该功能会在页面被更改时记录下来,这些信息将被写入一个紧凑的单独的所谓的位图文件中。xtrabackup 二进制文件将使用该文件来只读取增量备份所需的数据页面,这可能会节省很多读取请求。如果 xtrabackup 二进制文件找到位图文件,那么则默认启用后一种算法,当然,即使位图数据可用,也可以指定--incremental-force-scan参数读取所有页面,即使用第一种算法。

增量备份实际上不会将数据文件与先前备份的数据文件进行比较。实际上,如果你知道它的 LSN,则可以使用--incremental-lsn执行增量备份,而无需执行以前的备份。增量备份只需读取页面并将其 LSN 与最后一个备份的 LSN 进行比较即可。但是,你仍需要完整备份才能恢复增量更改;如果没有完整的备份作为基础,增量备份将毫无用处。所以要进行增量备份,需要先开始进行一个完整备份, xtrabackup 二进制文件会将名为 xtrabackup_checkpoints 的文件写入备份的目标目录。该文件包含一行 to_lsn 参数,这是此次备份结束时数据库的 LSN,也是下次增量备份的重要依据。

当你执行完一次完整备份后,如果你查看备份目录的 xtrabackup_checkpoints 文件,你应该看到类似于以下内容的一些内容:

现在你已经完成了一个完整备份,你可以根据它进行增量备份。此时增量备份目录的文件都会以 .delta 结尾,这些新数据代表自 LSN 1291135 以来的变化。

八、Xtrabackup有什么坑呢?

了解了 Xtrabackup 的原理之后,那么 Xtrabackup 会有什么坑呢?

从上文中介绍的 Xtrabackup 的备份流程和原理上,我们可以得知,Xtrabackup 工具备份过程中是不会出现 mysqldump 备份工具的”坑一:会造成 MyISAM 表跟 binlog pos 位点不一致”的问题。因为 Xtrabackup 备份工具是在所有事务表和非事务表都备份完成之后才会执行 UNLOCK TABLES 释放全局读锁,so…从加锁之后,解锁之前不可能有任何其他的 DML 请求能够对数据做修改,从而保证的备份数据的一致性。也就是说对于 MyISAM 表会一直加锁哦。

另外,我们知道,Xtrabackup 在备份事务表时,是没有对数据库加锁的,so..这个时候,其实 DDL 是允许执行的,Xtrabackup 持续在备份 innodb 事务表期间,如果被执行 DDL 的表是在 Xtrabackup 备份完成之后(针对此表而言)发起,那么在下一次 scan lsn 的时候 Xtrabackup 将发现 DDL 更改,报错终止。大概错误信息如下:

如果是在备份非事务表期间发起的 DDL,那么将被 FLUSH TABLE WITH READ LOCK 语句阻塞。所以,对于使用 Xtrabackup 备份的生产环境,要执行 DDL 语句,也需要避开备份时间。

那么,除了这个,还有其他坑吗?

Xtrabackup 备份过程中为了获得一个一致性备份,仍然会使用 FLUSH TABLES和FLUSH TABLES WITH READ LOCK 这两个语句对数据库进行刷新表缓存、加全局读锁,也就是说,mysqldump 使用这两个语句可能会踩到的坑,在 Xtrabackup 中也会碰到,如下:

1)如果一个会话中使用 LOCK TABLES 语句对某表加了表锁,在该表锁未释放前,那么另外一个会话如果执行 FLUSH TABLES和FLUSH TABLES WITH READ LOCK 语句会被阻塞,而如果数据库中 lock_wait_timeout 参数设置时间太短,innobackupex 将会因为执行 FLUSH TABLES WITH READ LOCK 语句获取全局读锁超时而导致备份失败退出。

2)如果一个会话正在执行 DDL 语句,那么另外一个会话如果执行 FLUSH TABLES和FLUSH TABLES WITH READ LOCK 语句会被阻塞,而如果数据库中 lock_wait_timeout 参数设置时间太短,innobackupex 将会因为执行 FLUSH TABLES WITH READ LOCK 语句获取全局读锁超时而导致备份失败退出。

3)、如果一个会话正在执行 DML 大事务(DML 语句正在执行,数据正在发生修改,而不是使用 lock in share mode 和 for update 语句来显式加锁),那么另外一个会话如果执行 FLUSH TABLES 和 FLUSH TABLES WITH READ LOCK 语句会被阻塞,而如果数据库中 lock_wait_timeout 参数设置时间太短,innobackupex 将会因为执行 FLUSH TABLES WITH READ LOCK 语句获取全局读锁超时而导致备份失败退出。

但是,细心的童鞋可能已经发现了,Xtrabackup 备份时的 general_log 中执行 FLUSH NO_WRITE_TO_BINLOG TABLES 语句之前,有这样一句语句:SET SESSION lock_wait_timeout=31536000,备份时会在 session 级别把锁超时时间改了,so…除了加表锁忘记释放之外,其他两种情况估计不太可能碰到锁超时的情况!!

当然,如果每天备份一次,那么我们不太可能让 Xtrabackup 在备份时,获取全局读锁时等待 31536000 秒,so……我们可以使用 Xtrabackup 的选项--kill-long-queries-timeout,来再获取全局读锁时,如果某查询阻塞了获得该 FLUSH TABLE WITH READ LOCK 语句时间超过这个阀值,那么就对该会话执行kill,杀掉这个连接,当然,你也许会说对数据做修改的不能杀,只能杀查询的,那么我们可以使用--kill-long-query-type=all|select选项。下面列出这俩选项的含义:

--kill-long-query-type=all|select

该选项指定哪些类型的查询在指定的查询时间之后还没有执行完成时被kill掉,以释放阻塞加全局读锁的锁,默认值为 all,有效值有:all 和 select。执行该选项需要有 process 和 super 权限。

--kill-long-queries-timeout=SECONDS

该选项指定 Xtrabackup 在执行 FLUSH TABLES WITH READ LOCK 时碰到阻塞其获得锁的查询时,等待该参数指定的秒数之后,如果仍然有查询在运行,则执行 kill 掉这些查询。默认值为 0,表示 Xtrabackup 不启用尝试 kill 掉任何查询的功能。

Note

很多人喜欢在备份前先 flush binary logs 一把,其实在有大事务对数据进行修改时,一不小心可能就会出现数据库 hang 死,所以不建议这么做。另外,Xtrabackup 备份期间,在数据库中创建的连接不要误杀,否则备份失败。

<参考>

xtrabackup throttle参数及相关问题分析

mysqldump与innobackupex备份过程你知多少

MySQL · 物理备份 · Percona XtraBackup备份原理

Xtrabackup备份原理实现细节——对淘宝数据库内核月报补充

[原理解析] XtraBackup 备份恢复时为什么要加apply-log-only参数?


如果您觉得本站对你有帮助,那么可以支付宝扫码捐助以帮助本站更好地发展,在此谢过。
喜欢 (1)
[资助本站您就扫码 谢谢]
分享 (0)

您必须 登录 才能发表评论!