0%

MySQL 备份之 Xtrabackup

Xtrabackup 是一个对 InnoDB 做数据备份的工具,支持在线热备份。

简介

Xtrabackup 是一个对 InnoDB 做数据备份的工具,支持在线热备份(备份时不影响数据读写),是商业备份工具 InnoDB Hotbackup 的一个很好的替代品。 –摘自百度百科


安装 XtraBackup

这里只介绍 yum 和 rpm 安装方法,其他安装方法查看:

yum 的安装方法

1
2
3
rpm -Uhv http://www.percona.com/downloads/percona-release/percona-release-0.0-1.x86_64.rpm
# 测试安装库,确保安装成功
yum list | grep percona

rpm 包安装

使用wget下载 rpm 包,然后通过 rpm 包安装


XtraBackup 使用手册

使用 innobackupex 脚本

innobackupex 是 perl 脚本对 xtrabackup 的封装,和功能扩展。

备份预备工作

  • 权限和连接
    xtrabackup 需要连接到数据库和 datadir 操作权限。
    xtrabackup 或者 innobackupex 在使用过程中设计到 2 类用户权限:
    1. 系统用户,用来调用 innobackupex 或者 xtrabackup
    2. 数据库用户,数据库内使用的用户
  • 连接到服务
    innobackupex 或者 xtrabackup 通过--user--password连接到数据库服务
    1
    2
    3
    innobackupex --user=DBUSER --password=SECRET /path/to/backup/dir/
    innobackupex --user=LUKE --password=US3TH3F0RC3 --stream=tar ./ | bzip2 -
    xtrabackup --user=DVADER --password=14MY0URF4TH3R --backup --target-dir=/data/bkps/
    其他连接选项:
    Option Description
    --port The port to use when connecting to the database server with TCP/IP.
    --socket The socket to use when connecting to the local database.
    --host The host to use when connecting to the database server with TCP/IP.
  • 需要的权限
    连接到服务是为了执行备份,需要在 datadir 上有 read,write 和 execute 权限。
    1
    2
    3
    CREATEUSER 'backuser'@'localhost' IDENTIFIED BY 's3cret';
    GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.*TO 'backuser'@'localhost';
    FLUSH PRIVILEGES;
    在数据库中需要以下权限:
    • RELOAD 和 LOCK TABLES 权限为了执行 FLUSH TABLES WITH READ LOCK。
    • REPLICATION CLIENT 为了获取 binary log 位置
    • CREATE TABLESPACE 权限为了导入表,用户表级别的恢复
    • SUPER 权限在 slave 环境下备份用来启动和关闭 slave 线程

全备和全备还原

  • 使用 innobackupex 创建全备

    1
    innobackupex --user=DBUSER --password=DBUSERPASS /path/to/BACKUP-DIR/

    从信息中会发现备份被创建在 /path/to/BACKUP-DIR/2013-03-25_00-00-09
    内部机制:
     在备份的时候 innobackupex 会调用 xtrabackup 来备份 innodb 表,并复制所有的表定义,其他引擎的表(MyISAM,MERGE,CSV,ARCHIVE)。
    其他选项:
    --no-timestamp,指定了这个选项备份会直接备份在 BACKUP-DIR,不再创建时间戳文件夹。
    --default-file,指定配置文件,用来配置 innobackupex 的选项。

  • 使用 innobackupex 预备全备
    创建完备份之后数据被没有马上可以被还原,需要回滚未提交事务,前滚提交事务,让数据库文件保持一致性。
    innobackupex 使用--apply-log来做预备备份

    1
    innobackupex --apply-log /path/to/BACKUP-DIR

    成功后,备份可以被用来还原数据库了。
    内部机制:
     读取备份文件夹中的配置文件,然后 innobackupex 重做已提交事务,回滚未提交事务,之后数据就被写到了备份的数据文件(innodb文件)中,  并重建日志文件。这一步隐式调用了2次 xtrabackup prepare。更多关于 xtrabackup 可以看之后的章节。
    其他选项:
    --use-memory:指定预备阶段可使用的内存,内存多则速度快,默认为10MB

    1
    innobackupex --apply-log --use-memory=4G /path/to/BACKUP-DIR
  • 使用 innobackupex 还原备份 使用--copy-back 还原备份

    1
    2
    # --default-files 可以修改默认使用的配置文件
    innobackupex --default-files=/etc/my.cnf --copy-back /path/to/BACKUP-DIR

    根据 my.cnf 复制所有备份到 datadir 下:
    datadir 必须是为空的,--copy-back 不会覆盖已存在的文件,还要注意,还原时需要先关闭服务,如果服务是启动的,那么就不能还原到 datadir。

    • 修改文件的所有者和权限:
      1
      2
      # 默认MySQL数据文件位置
      chown -R mysql:mysql /var/lib/mysql

增量备份和还原

  • 为了减少空间使用和备份的时间;
  • 增量备份的实现,依赖于 innodb 页上面的 LSN(log sequence number),每次对数据库的修改都会导致 LSN 自增;
  • 增量备份会复制指定 LSN 之后的所有数据页。

创建全量备份

  • 全量备份 在创建增量备份之前需要一个全备,不然增量备份是没有意义的。

    1
    innobackupex /data/backups

    这样就会在 /data/backups 下创建一个时间戳文件夹,如 /data/backups/2013-03-31_23-01-18,然后文件夹内是备份文件。
    检查备份文件夹下的 xtrabackup-checkpoints,会有一下信息(示例):

    backup_type = full-backuped  
    from_lsn =0  
    to_lsn =1291135  
    

创建第一个增量备份

  • 使用--incremental创建增量备份

    1
    innobackupex --incremental /data/backups --incremental-basedir=BASEDIR

    BASEDIR 指向之前的全备, /data/backups/2013-03-31_23-01-18,成功后备份会生成在 /data/backups 下的时间戳目录中, 如:/data/backups/2013-04-01_23-01-18 ,把这个目录叫为记为 INCREMENTAL-DIR-1 方面之后使用。
    然后查看 xtrabackup-checkpoints:

    backup_type = incremental  
    from_lsn =1291135  
    to_lsn =1352113  
    

    可以发现和全备不同的是,backup_type 为 incremental,from_lsn 不为 0。

  • 再创建一个增量备份 在INCREMENTAL-DIR-1 的基础上再创建一个增量备份,记为 INCREMENTAL-DIR-2。

    1
    innobackupex --incremental /data/backups --incremental-basedir=INCREMENTAL-DIR-1
  • 增量备份替代方法 可以使用指定 --incremental-lsn 来代替 --incremental-basedir 的方法创建增量备份。

    1
    2
    innobackupex --incremental /data/backups --incremental-lsn=1291135
    innobackupex --incremental /data/backups --incremental-lsn=1358967

    xtrabackup 只会影响 xtradb 或者 innodb 的表,其他引擎的表在增量备份的时候只会复制整个文件,不会差异。

预备增量备份
  • 预备增量备份需要 2 个步骤:

    • 需要先预备全备,但是只重做已提交事务,不回滚未提交事务,然后应用到全备,也是只重做已提交事务,不回滚未提交事务
    • 回滚未提交事务
      如果已经回滚了未提交事务,那么就无法再应用增量备份。
      在 mariadb 10.0 上测试发现不加 --redo-only 预备全备,然后使用 --redo-only 应用增量备份,MySQL 服务能够正常启动并且数据被成功 还原在全备上,使用--redo-only只做已提交事务,不回滚未提交事务
      1
      innobackupex --apply-log --redo-only BASE-DIR
  • 应用第一个增量备份

    1
    innobackupex --apply-log --redo-only BASE-DIR --incremental-dir=INCREMENTAL-DIR-1

    如果没有指定--incremental-dir,那么 innobackupex 会使用最近的一个在 basedir 中被创建的子目录。

  • 应用另外一个备份

    1
    innobackupex --apply-log BASE-DIR --incremental-dir=INCREMENTAL-DIR-2

    因为是最后一个增量备份所以没有必要再加--redo-only,这样最后一个增量也被应用到全备上了。

    --redo-only 除了最后一个不用加之外,其他的增量应用都要加,最后一个应用的时候可以直接进入回滚未提交事务阶段。如果加了也没事,服务启动的 时候会进入 recovery 过程,来回滚。

    需要注意的是,应用增量备份的时候只能按照备份的顺序来应用。如果应用顺序错误,那么备份就不可用。如果无法确定顺序, 可以使用 xtrabackup-checkpoints来确定顺序。

  • 回滚未提交事务
    当应用完所有增量备份的时候,就需要回滚所有为完成事务(如果最后一步加了 --redo-only 就需要回滚未提交,不执行的话在服务启动阶段服务会 处理未提交事务)。

    1
    innobackupex --apply-log BASE-DIR

    Note that the iblog* files will not be created by innobackupex, if you want them to be created, use xtrabackup –prepare on the directory. Otherwise, the files will be created by the server once started.

    文中提到 innodb 事务日志(iblog*)不会被创建,但是测试下使用了最后一步回滚未提交事务发现有 iblog* 文件,而且上文提到 innobackupex 会隐式执行两次 xtrabackup –prepare,在下文介绍 xtrabackup 时会提到,执行2次 xtrabackup --preare会创建 iblog* 文件,与文中提到不符。

还原增量备份

还原增量备份其实和还原全备一样

1
innobackupex --copy-back BASE-DIR

注意事项可以看:使用 innobackupex 还原备份

可以使用流(stream)做增量备份
  • 先进行一个全备 shell innobackupex /data/backups

  • 备份本地

    1
    innobackupex --incremental --incremental-lsn=LSN-number --stream=xbstream ./ > incremental.xbstream
    • 解包方法
      1
      xbstream -x < incremental.xbstream
  • 使用本地备份流到远程并解包

    1
    2
    innobackupex  --incremental --incremental-lsn=LSN-number --stream=xbstream ./ | /
    ssh user@hostname " cat - | xbstream -x -C > /backup-dir/"

部分备份和还原

 xtrabackup 可以使用部分备份,但是只能在一个表一个文件的状况下才能使用,设置 MySQL 选项:innodb_file_per_table。 还原部分备份使用表导入的方式,而不是 --copy-back 选项。 尽管很多场景下可以通过直接复制文件的方式,但是会产生一致性问题不建议使用。

创建部分备份

部分备份有3个选项可以使用:

  • --include:设置正则表达式的格式,匹配的就备份

  • --table-file:在文件中指定要备份的表,然后通过这个选项传入文件

  • --databases:指定数据库列表

  • 使用 include 方式
    include 方式数据库名也可以匹配:

    1
    innobackupex --include='^mydatabase[.]mytable' /path/to/backup                 

    这个选项是传给 xtrabackup --tables,所有的数据库目录都会被创建,但是里面可能是空的。

  • 使用tables-file方式

    1
    2
    echo "mydatabase.mytable" > /tmp/tables.txt
    innobackupex --tables-file=/tmp/tables.txt /path/to/backup

    这个选项是应用xtrabackup --table-file,只有匹配到表的数据库目录才会被创建

  • 使用 databases 方式
    innobackupex 可以传递用空格隔开的数组,格式为:database_name[.tablename]

    1
    innobackupex --databases="mydatabase.mytable mysql" /path/to/backup

    --databases选项只会对非 innodb 引擎表和 frm 文件产生影响,对于 innodb 数据文件总是备份的

预备部分备份

部分备份的预备需要使用--export

1
innobackupex --apply-log --export /path/to/partial/backup

会出现以下,是因为 innodb 表保存了数据文件但是没有保存 frm 文件。

111225  0:54:06  InnoDB: Error: table 'mydatabase/mytablenotincludedinpartialb'
InnoDB: in InnoDB data dictionary has tablespace id 6,
InnoDB: but tablespace with that id or name does not exist. It will be removed from data dictionary.

之后会发现生成了 .exp 和 .cfg 文件。exp 文件适用于 percona server,cfg 适用于 mariadb 和 MySQL。mariadb 10.0 可以直接通过 ibd 和 frm 文件 import。 MySQL 5.6 之后可以不使用 cfg 来进行 import,cfg 如果存在会被用来做表结构的验证。

在已经预备好的备份上,可以使用 --export--apply-log 创建 .exp 文件。

还原部分备份
  • 创建表 表结构需要和被还原的一样。

    1
    CREATE TABLE mytable (...) ENGINE=InnoDB;
  • discard表空间

    1
    ALTER TABLE mydatabase.mytable DISCARD TABLESPACE;

    之后把文件复制到相应的目录下(注意文件的所有者和文件权限),需要文件 .ibd,.exp 或者 .cfg 文件(.cfg 文件用户 MySQL5.6)。

  • import表空间

    1
    ALTER TABLE mydatabase.mytable IMPORT TABLESPACE;

窄备份

窄备份指不备份 secondary 索引数据。这样可以减少备份的大小。缺点就是需要重建索引,会很慢。

创建窄备份
1
innobackupex --compact /data/backups

创建了之后查看 xtrabackup_checkpoint

backup_type = full-backuped
from_lsn =0
to_lsn =2888984349
last_lsn =2888984349
compact =1

compact=1 说明该备份是窄备份。

预备窄备份

在预备窄备份的时候需要使用--rebuild-indexes来重新创建索引

1
innobackupex --apply-log --rebuild-indexes /data/backups/2013-02-01_10-29-48

从输出上可以看到索引被重建

130201 10:40:20  InnoDB: Waiting for the background threads to start
Rebuilding indexes for table sbtest/sbtest1 (space id: 10)
Found index k_1
Dropping 1 index(es).
Rebuilding 1 index(es).
Rebuilding indexes for table sbtest/sbtest2 (space id: 11)
Found index k_1
Found index c
Found index k
Found index c_2
Dropping 4 index(es).
Rebuilding 4 index(es).

对于增量备份的应用可以先不重建索引,在应用最后一个差异备份的时候使用 --rebuild-index 来创建索引,每次都应用都重建索引太花时间。

为了重建速度,可以使用并发创建索引,使用参数--rebuild-threads指定并发数。

还原窄备份

窄备份还原和全备还原一样直接使用 --copy-back选项。
具体看:使用 innobackupex 还原备份

备份加密

具体看:Encrypted Backups

其他功能

备份压缩和流

  Stream 模式下,Xtrabackup 的 STDOUT 可以指定 tar 或者 xbstream 格式输出。流允许,其他程序过滤备份输出,提供更大的灵活 存储 backup。 使用流特性,需要指定--stream选项

1
innobackupex --stream=tar /tmp

 innobackupex 会用子程序启动 xtrabackup --log-stream 定向到临时文件,然后使用 xbstream 把所有数据文件 stream 到 STDOUT。 当压缩启动,xtrabackup 压缩所有输出数据,但是元数据和非 innodb 文件不能被压缩。现在唯一支持的压缩算法是 quicklz。会生产 qpress 归档 格式的文件。 使用 xbstream 可以平法复制压缩可以提高备份速度。

  • 使用 xbstream 流备份

    1
    innobackupex --stream=xbstream /root/backup/ > /root/backup/backup.xbstream
  • 使用流压缩

    1
    innobackupex --stream=xbstream --compress /root/backup/ > /root/backup/backup.xbstream
  • 解包

    1
    bstream -x < backup.xbstream -C /root/backup/
  • 流压缩并备份到另外一台机器

    1
    innobackupex --compress --stream=xbstream /root/backup/ | ssh user@otherhost "xbstream -x -C /root/backup/"
  • 使用 tar 备份

    1
    innobackupex --stream=tar /root/backup/ > /root/backup/out.tar
  • 使用 tar 流并备份到其他服务器

    1
    innobackupex --stream=tar ./ | ssh user@destination \ "cat - > /data/backups/backup.tar"
  • 提取 tar 流,需要加 i 参数

    1
    tar -xizf backup.tar.gz
  • 也可以压缩流

    1
    2
    innobackupex --stream=tar ./ | gzip - > backup.tar.gz
    innobackupex --stream=tar ./ | bzip2 - > backup.tar.bz2
在复制环境下备份

有 2 个选项用于从复制环境下备份

  • slave-info
    --slave-info,会打印 binary log 的位置和 master server 名,并且以 change master 的方式写到 xtrabackup_slave_info 中。
  • safe-slave-backup
    --safe-slave-backup,为了保证复制状态的一致性。(这个选项会关闭 slave sql 线程,等待直到 SHOW STATUS 中的 slave_open_temp_tabls 为 0 才启动备份。如果等待时间超过 --safe-slave-backup-timeout(默认 300 秒) 就会报错。 备份成功后 slave sql thread 会自动启动。
加速备份进程

使用 parallel 和 compress-threads 加速
当有多个文件时,可以使用使用 --parallel 加速备份,这个选项会指定 xtrabackup 备份文件的线程数。

1
innobackupex --parallel=4 /path/to/backup
  • 使用 xbstream
    可以考虑通过 --compress-threads 加速压缩进程,默认为 1.

    1
    innobackupex --stream=xbstream --compress --compress-threads=4 ./ > backup.xbstream
  • 使用 rsync 加速
    为了加速复制过程,最小化 FLUSH TABLES WITH READ LOCK 堵塞时间,使用 innobackupex --rsync。 使用了这个选项所有文件都会在一个 cp 命令里面,而不是每个文件一个 cp。并且 innobackupex 会调用 2 次 rsync, 一次在执行 FLUSH TABLES WITH READ LOCK 之前,一次在之后。第二次执行的时候会把第一次之后的修改过的数据。

节流(throttling)备份

尽管 innobackupex 不会堵塞数据库操作,但是备份终会消耗系统资源。为了减少资源消耗,可以使用 --throttle 来限制每秒钟读写对次数。

还原独立表

使用 xtrabackup 来导出指定表,然后导入到 XtraDB 或者 MySQL 5.6(测试可以导入 mariadb 10.0) mariadb 10.0 可以直接复制 ibd 然后通过 import tablespace 导入。

  • 导出表
    导出表使用--export选项:

    1
    innobackupex --apply-log --export /path/to/backup

    会在发现多了一个 .exp 文件和 .cfg 文件(用于不同的 MySQL 版本)

    1
    find /data/backups/MySQL/ -name export_test.*
  • 导入表
    先创建一个表,表结构需要和被还原的一样。

    1
    CREATE TABLE mytable (...) ENGINE=InnoDB;
  • discard 表空间

    1
    ALTER TABLE mydatabase.mytable DISCARD TABLESPACE;

    之后把文件复制到相应的目录下(注意文件的所有者和文件权限),需要文件 .ibd,.exp 或者 .cfg 文件(.cfg 文件用户 MySQL5.6)。

  • import 表空间

    1
    ALTER TABLE mydatabase.mytable IMPORT TABLESPACE;
时间点还原

和 MySQL 手册中介绍的时间点还原一样,xtrabackup 也是通过 binary log 进行时间点还原。

  • 先进行备份

    1
    innobackupex /path/to/backup --no-timestamp
  • 进行预备

    1
    innobackupex --apply-log /path/to/backup
  • 在服务器中找出操作 binary log 和当前 binary log 状态

    1
    2
    # 查看binary log
    SHOW BINARY LOGS;

    显示信息如下:

      +------------------+-----------+
      | Log_name         | File_size |
      +------------------+-----------+
      | MySQL-bin.000001 |       126 |
      | MySQL-bin.000002 |      1306 |
      | MySQL-bin.000003 |       126 |
      | MySQL-bin.000004 |       497 |
      +------------------+-----------+
    
    1
    2
    # 查看master
    SHOW MASTER STATUS;

    显示信息如下:

      +------------------+----------+--------------+------------------+
      | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
      +------------------+----------+--------------+------------------+
      | MySQL-bin.000004 |      497 |              |                  |
      +------------------+----------+--------------+------------------+
    

    然后查看 xtrabackup_binlog_info 确定备份的 binary log 位置:

    1
    cat /path/to/backup/xtrabackup_binlog_info

    MySQL-bin.000003 57

  • 还原数据库

    1
    innobackupex --copy-back /path/to/backup
  • 然后使用 mysqlbinlog 取出 binary log 中的记录,然后输出到文件

    1
    mysqlbinlog /path/to/datadir/MySQL-bin.000003 /path/to/datadir/MySQL-bin.000004 --start-position=57 > mybinlog.sql
  • 然后检查输出的文件,确定要恢复到的位置,然后执行恢复

    1
    2
    mysqlbinlog /path/to/datadir/MySQL-bin.000003 /path/to/datadir/MySQL-bin.000004 \
    --start-position=57 --stop-datetime="11-12-25 01:00:00" | MySQL -u root -p
提高对 FLUSH TABLES WITH READ LOCK 控制

  在备份的时候,为了保证数据一致性,在备份非 innodb 表的之前会先使用 FLUSH TABLES WITH READ LOCK,这个语句在有长时间查询 运行的情况下也能执行,但是其他的所有事都会被堵塞,Waiting for table flush 或者 Waiting for master to send event, 这个时候不应该 kill FLUSH TABLES WITH READ LOCK,而是应该 kill 掉那个大的查询。因为当有大的查询的时候,FLUSH TABLES WITH READ LOCK 会被卡住。

为了能够避免这种事情发生需要实现 2 个事情:

  1. innobackupex 等一个好的时机运行
  2. innobackupex 可以 kiil 所有查询或者只能存在 SELECT 查询。即 kill 所有阻止获取全局锁的查询。
  • 等待查询完成
    为了避免 innobackupex 等待 FLUSH TABLES WITH READ LOCK 执行太长时间,可以使用 innobackupex --lock-wait-timeout, 可以用来限制等待时间,一旦超时就会报错退出。

  • 设置等待查询的类型
    innobackupex --lock-wait-query-type 可取的值是 all 或者 update,如果为 all 那么会等待所有长运行查询完成, 如果是 update,会等待除 select 之外的 DML 完成。 --lock-wait-threshold 用来定义 --lock-wait-query-type 中的长运行查询,如果超过 --lock-wait-threshold 都算长运行查询。

  • Kill 堵塞查询
    innobackupex 可以 kill 所有阻止获取全局锁的查询。 可以通过指定 --kill-long-queries-timeout 用来指定执行 FLUSH TABLES WITH READ LOCK 后还可以执行的时间,0 为不 kill, --kill-long-query-type 用来指定超时之后,kill 的查询类型,可以是 all 或者 select。

    例如:

    1
    2
    innobackupex --lock-wait-threshold=40 --lock-wait-query-type=all --lock-wait-timeout=180 --kill-long-queries-timeout=20\
    --kill-long-query-type=all /data/backups/

innobackupex 工作原理

innobackupex 是 perl 脚本,封装了 xtrabackup 和 tar4ibd 的功能。

备份

  如果没有指定,innobackupex 默认认为是备份模式。默认 innobackupex 会以 --suspend-at-end 启动 xtrabackup,来 复制 innodb 文件。当 xtrabackup 复制完成,innobackupex 发现创建的 xtrabckup_suspended_2 文件,就执行 FLUSH TABLES WITH READ LOCK 复制其他文件。

xtrabackup 的确定,如果运行的时候没有带 ibbackup 参数,那么 innobackupex 会从 xtrabackup_binary 上找,然后读取要启动 xtrabackup 的 二进制文件。否则只能通过连接 MySQL 服务确定使用的二进制文件。如果不能连接就错误。

决定好二进制文件之后,断开连接以二进制方式启动 binary。如果不是增量备份,连接到服务,如果启动了 --safe-slave-backup 等待 slave, 然后获取全局 read lock,防止其他引擎的表被修改,读锁只锁定非 innodb 表,并且在 innodb 表复制完数据和日志后进行。

当所有文件备份完之后,恢复 ibbackup 并等待完成对事务复制,复制在备份期间生产的事务。然后释放表锁,slave 启动并且连接关闭, 然后删除 xtrabckup_suspended_2 文件。

还原

还原数据库使用--copy-back选项

  innobackupex 通过读取 my.cnf 中的 datadir, innodb_data_home_dir, innodb_data_file_path,innodb_log_group_home_dir 并检查目录是否存在。然后复制 MyISAM 表,索引,然后复制 innodb 表和索引,最后日志文件。复制的时候会保留文件属性,需要修改用户所有者。 恢复除了 --cop-back 也可以使用 --move-back,不同的是一个是复制,一个是移动。

Reference

主要介绍一些选项:The innobackupex Option Reference


使用 Xtrabackup

选择 bianry

Xtrabackup 有 4 个 binary:Xtrabackup,Xtrabackup_51,Xtrabackup_55,Xtrabackup_56。 服务和 binary 对照:

Server xtrabackup binary
MySQL 5.1.* xtrabackup_51
MySQL 5.1.* with InnoDB plugin xtrabackup
MySQL 5.5.* xtrabackup_55
MySQL 5.6.* xtrabackup_56
MariaDB 5.1.* xtrabackup
MariaDB 5.2.* xtrabackup
MariaDB 5.3.* xtrabackup
MariaDB 5.5.* xtrabackup_55
MariaDB 10.0.* xtrabackup_56
Percona Server 5.0 xtrabackup
Percona Server 5.1 xtrabackup_51
Percona Server 5.5 xtrabackup_55
Percona Server 5.6 xtrabackup_56

配置 Xtrabackup

  所有的 Xtrabackup 配置都是通过选项设置,可以是命令行参数,也可以通过配置文件 my.cnf。 xtrabackup 会读取 [MySQL],[xtrabackup] 选项,若 Xtrabackup 读入,会覆盖 [MySQL] 的选项。 并不是所有的配置都要写入配置文件,写配置文件只是为了方便。

xtrabackup 并不接受和 MySQLd 一样的语法,有些语法不支持如,--set-variable=<variable>=<value> 要用 --variable=value 语法。 xtrabackup 并不需要特殊的存储,但是如果是 NFS 并不是以 rsync 挂载,那么在执行 rsync 的时候可能并不是真正的同步数据。

创建全备和还原

创建全备

使用 xtrabackup 创建全备需要指定选项 --backup,还需要指定 --target_dir,如果 target 不存在,会创建一个,如果存在那么如果是空的就会成功, 如果不是空的,不会覆盖已存在文件,并且报错。

主要完成 2 个任务:

  1. 开启一个 log copy 线程,用来监控 innodb 日志文件(ib_logfile*),如果修改就复制到 xtrabackup_logfile,因为复制会持续很长时间, 所以恢复进程需要所有从备份开始到结束的所有日志。
  2. 复制 innodb 数据文件到目标目录,这个并不是简单的复制,是和 innodb 引擎一样,从数据目录中一页一页的复制。

当数据文件完成复制,xtrabackup 会停止对日志的复制,并在目标目录中创建 xtrabackup_checkpoin t文件。

1
xtrabackup --backup --datadir=/var/lib/MySQL/ --target-dir=/data/backups/MySQL/

在备份输出的时候,可以看到日志的复制。

>> log scanned up to (3646475465483)
>> log scanned up to (3646475517369)
>> log scanned up to (3646475581716)
>> log scanned up to (3646475636841)
>> log scanned up to (3646475718082)
>> log scanned up to (3646475988095)
>> log scanned up to (3646476048286)
>> log scanned up to (3646476102877)
>> log scanned up to (3646476140854)

[01] Copying /usr/local/MySQL/var/ibdata1

     to /usr/local/MySQL/Backups/2011-04-18_21-11-15/ibdata1

[01]        ...done

日志复制线程是每秒检查一次,查看是否有新的日志被写入,因为日志文件是被回绕写的,所以日志复制线程要更上日志文件的修改,如果没有复制日志被覆盖 了,那么就会报错。

备份的时间长短依赖于数据库的大小,然后时间都可以停止数据库,因为不会去修改数据库数据。

预备全备

 备份完数据库之后,下一步是预备数据库,因为数据文件在某个时间点上,并不是一致的,所以需要预备让数据文件在某个时间点一致,--prepare 就是让数据文件保持一致性。

在 innobackupex --apply-log 的时候,innodb h会自动读取配置文件 my.cnf,使用 --defaults-file=xxx 来指定一个配置文件, 传递给 xtrabackup 用于预备数据库备份。

  可以在任何机器上进行预备,没必要在原服务器或者要还原的服务器上进行。在恢复阶段,xtrabackup 嵌入了修改过的 innodb,禁止了 innodb 的标准安全监察,如日志文件大小是否准确。prepare 阶段就是使用这个嵌入的 innodb 来做通过日志文件对数据文件进行 crash 恢复。

1
xtrabackup --prepare --target-dir=/data/backups/MySQL/

当预备完成就会有以下输出:

101107 16:40:15  InnoDB: Shutdown completed; log sequence number <LSN>

  现在备份一致性已经没问题了,可以准备还原,但是为了能够更快还原,可以再执行一次预备,第一次执行的时候只让数据文件保持一致性,并 没有创建日志文件。第二次执行的时候会创建日志文件。如果第一次预备后还原,启动服务,服务会自动创建日志文件,但是比较花费时间。

当第二次运行预备的时候有一下输出:

1
xtrabackup --prepare --target-dir=/data/backups/MySQL/
xtrabackup: This target seems to be already prepared.
xtrabackup: notice: xtrabackup_logfile was already used to '--prepare'.
101107 16:54:10  InnoDB: Log file ./ib_logfile0 did not exist: new to be created
InnoDB: Setting log file ./ib_logfile0 size to <SIZE> MB
InnoDB: Database physically writes the file full: wait...
101107 16:54:10  InnoDB: Log file ./ib_logfile1 did not exist: new to be created
InnoDB: Setting log file ./ib_logfile1 size to <SIZE> MB
InnoDB: Database physically writes the file full: wait...
101107 16:54:15  InnoDB: Shutdown completed; log sequence number 1284108

如果是第二次运行,运行时会有以下提示:

xtrabackup: This target seems to be already prepared.
xtrabackup: notice: xtrabackup_logfile was already used to '--prepare'.

不推荐在执行预备的时候终端过程,这样可能会导致数据文件异常。 如果视图要加入增量备份,那么使用 --apply-log-only,不然加不上增量备份。

还原全备

xtrabackup 没有什么功能来还原备份,可以直接通过 rsync,cp 来还原数据库

注意:注意保持 datadir 必须是空的,并且 MySQL 服务是停止的。不能还原到已经在运行的 MySQL 服务中。

1
2
3
4
# 通过rsync还原
rsync -avrP /data/backup/ /var/lib/MySQL/
# 还原后修改所有者
chown -R MySQL:MySQL /var/lib/MySQL

xtrabackup 只备份 innodb 数据文件,不会备份其他引擎的表,和 frm 文件。如果要对整个库备份还原可以使用 innodbbackupex

增量备份和还原

增量备份

增量备份原理

xtrabackup 和 innobackupex 都可以实现增量备份,也就是说只备份修改过的数据。 增量备份实现,依赖于 innodb 页中的 LSN(log sequence number) 增量备份会复制比之前的增量或者全备新的 lsn 页。 有 2 个算法找这样的页:

  1. 直接扫描数据页,并复制大于上次全备或者增量的 lsn 的页
  2. 类似 percona server,启动 changed page tracking 会记录页的修改。这样的记录会被保存在一个 map 文件中。 xtrabackup 会使用这个文件读取需要备份的页数据。当然也可以使用 --incremental-force-scan 强制扫描所有数据页。

增量备份并不是完整的数据,如果没有上次的备份,可以使用指定 --incremental-lsn 来进行增量备份。增量备份只会备份比指定 lsn 大的数据页。 当然需要全备来还原增量备份,不然增量备份是没有意义的。

创建增量备份
  • 首先创建全备

    1
    xtrabackup --backup --target-dir=/data/backups/base --datadir=/var/lib/MySQL/

    查看 xtrabackup_checkpoint 信息:

    backup_type = full-backuped
    from_lsn =0
    to_lsn =1291135
    
  • 进行增量备份:

    1
    2
    xtrabackup --backup --target-dir=/data/backups/inc1 \
    --incremental-basedir=/data/backups/base --datadir=/var/lib/MySQL/

    在 /data/backups/inc1 下包含了 delta 文件,如果 ibdata1.delta 和 test/table1.ibd.delta,检查增量备份的 xtrabackup_checkpoint:

    backup_type = incremental from_lsn =1291135 to_lsn =1291340

在做一个增量备份:

1
2
xtrabackup --backup --target-dir=/data/backups/inc2 \
--incremental-basedir=/data/backups/inc1 --datadir=/var/lib/MySQL/
预备增量备份

预备增量备份和在 innobackupex 一样,先不回滚方式应用全备,然后应用增量备份。 在 innobackupex 上使用 --apply-log-only 来重做,但不回滚。

  • 已有备份

    /data/backups/base
    /data/backups/inc1
    /data/backups/inc2
    
  • 预备全备,不回滚未提交事务

    1
    xtrabackup --prepare --apply-log-only --target-dir=/data/backups/base

    成功后输出:

    101107 20:49:43  InnoDB: Shutdown completed; log sequence number 1291135
    
  • 应用第一个增量备份

    1
    2
    xtrabackup --prepare --apply-log-only --target-dir=/data/backups/base \
    --incremental-dir=/data/backups/inc1

    增量备份被应用到 /data/backups/base,应用后输出:

    incremental backup from 1291135 is enabled.
    xtrabackup: cd to /data/backups/base/
    xtrabackup: This target seems to be already prepared.
    xtrabackup: xtrabackup_logfile detected: size=2097152, start_lsn=(1291340)
    Applying /data/backups/inc1/ibdata1.delta ...
    Applying /data/backups/inc1/test/table1.ibd.delta ...
    .... snip
    101107 20:56:30  InnoDB: Shutdown completed; log sequence number 1291340
    
  • 应用最后一个增量备份

    1
    2
    xtrabackup --prepare --target-dir=/data/backups/base \
    --incremental-dir=/data/backups/inc2

除了最后一个外其他的都要使用 --apply-log-only,如果最后一个也用了 --apply-log-only,就还原了文件还是一直的,但是没有回滚未提交事务, 当服务启动的时候会自动回滚未提交事务。

使用归档日志做增量备份

原理

在 percona server 5.6.11-60.3 加入了新功能,为 xtradb 日志归档,这个功能是,在老的日志文件被重写之前会被复制,因此保存了所有的 redo 日志。 归档日志的文件格式,ib_log_archive_,LSN 表示这个归档文件开始的 lsn。

ib_log_archive_00000000010145937920
ib_log_archive_00000000010196267520

这个功能由 innodb_log_archive 启动,保存的位置为 innodb_log_arch_dir(默认为数据文件夹)。

创建备份

1
2
# 创建一个全备
xtrabackup_56 --backup --target-dir=/data/backup/ --datadir=/var/lib/MySQL/

xtrabackup_checkpoint如下:

  backup_type = full-backuped
  from_lsn =0
  to_lsn =1546908388
  last_lsn =1574827339
  compact =0

使用归档日志来预备备份

1
xtrabackup_56 --prepare --target-dir=/data/backup/ --innodb-log-arch-dir=/data/archived-logs/

执行后查看 xtrabackup_checkpoint,backup-type 被修改:

backup_type = full-prepared
from_lsn =0
to_lsn =1546908388
last_lsn =1574827339
compact =0

另外也可以指定时间点预备:

1
xtrabackup_56 --prepare --target-dir=/data/backup/ --innodb-log-arch-dir=/data/archived-logs/ --to-archived-lsn=5536301566