MySQL Xtrabackup 备份实战
Percona Xtrabackup 实战指南:全量备份、增量备份、压缩备份、流式备份及主从环境下的备份恢复流程。
MySQL 备份之 Xtrabackup
Xtrabackup 是一个对 InnoDB 做数据备份的工具,支持在线热备份。
简介
Xtrabackup 是一个对 InnoDB 做数据备份的工具,支持在线热备份(备份时不影响数据读写),是商业备份工具 InnoDB Hotbackup 的一个很好的替代品。 —摘自百度百科
安装 XtraBackup
这里只介绍 yum 和 rpm 安装方法,其他安装方法查看:
yum 的安装方法
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 类用户权限:- 系统用户,用来调用 innobackupex 或者 xtrabackup
- 数据库用户,数据库内使用的用户
-
连接到服务
innobackupex 或者 xtrabackup 通过--user和--password连接到数据库服务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 权限。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 创建全备
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来做预备备份innobackupex --apply-log /path/to/BACKUP-DIR成功后,备份可以被用来还原数据库了。
内部机制:
读取备份文件夹中的配置文件,然后 innobackupex 重做已提交事务,回滚未提交事务,之后数据就被写到了备份的数据文件(innodb文件)中, 并重建日志文件。这一步隐式调用了2次 xtrabackup prepare。更多关于 xtrabackup 可以看之后的章节。
其他选项:
--use-memory:指定预备阶段可使用的内存,内存多则速度快,默认为10MBinnobackupex --apply-log --use-memory=4G /path/to/BACKUP-DIR -
使用 innobackupex 还原备份 使用
--copy-back还原备份# --default-files 可以修改默认使用的配置文件 innobackupex --default-files=/etc/my.cnf --copy-back /path/to/BACKUP-DIR根据 my.cnf 复制所有备份到 datadir 下:
datadir 必须是为空的,--copy-back不会覆盖已存在的文件,还要注意,还原时需要先关闭服务,如果服务是启动的,那么就不能还原到 datadir。- 修改文件的所有者和权限:
# 默认MySQL数据文件位置 chown -R mysql:mysql /var/lib/mysql
- 修改文件的所有者和权限:
增量备份和还原
- 为了减少空间使用和备份的时间;
- 增量备份的实现,依赖于 innodb 页上面的 LSN(log sequence number),每次对数据库的修改都会导致 LSN 自增;
- 增量备份会复制指定 LSN 之后的所有数据页。
创建全量备份
- 全量备份
在创建增量备份之前需要一个全备,不然增量备份是没有意义的。
这样就会在 /data/backups 下创建一个时间戳文件夹,如 /data/backups/2013-03-31_23-01-18,然后文件夹内是备份文件。innobackupex /data/backups
检查备份文件夹下的 xtrabackup-checkpoints,会有一下信息(示例):
backup_type = full-backuped
from_lsn =0
to_lsn =1291135
创建第一个增量备份
- 使用
--incremental创建增量备份
BASEDIR 指向之前的全备, /data/backups/2013-03-31_23-01-18,成功后备份会生成在 /data/backups 下的时间戳目录中, 如:/data/backups/2013-04-01_23-01-18 ,把这个目录叫为记为 INCREMENTAL-DIR-1 方面之后使用。innobackupex --incremental /data/backups --incremental-basedir=BASEDIR
然后查看 xtrabackup-checkpoints: backup_type = incremental
from_lsn =1291135
to_lsn =1352113
可以发现和全备不同的是,backup_type 为 incremental,from_lsn 不为 0。 - 再创建一个增量备份
在INCREMENTAL-DIR-1 的基础上再创建一个增量备份,记为 INCREMENTAL-DIR-2。
innobackupex --incremental /data/backups --incremental-basedir=INCREMENTAL-DIR-1 - 增量备份替代方法
可以使用指定
--incremental-lsn来代替--incremental-basedir的方法创建增量备份。
xtrabackup 只会影响 xtradb 或者 innodb 的表,其他引擎的表在增量备份的时候只会复制整个文件,不会差异。innobackupex --incremental /data/backups --incremental-lsn=1291135 innobackupex --incremental /data/backups --incremental-lsn=1358967
预备增量备份
-
预备增量备份需要 2 个步骤:
- 需要先预备全备,但是只重做已提交事务,不回滚未提交事务,然后应用到全备,也是只重做已提交事务,不回滚未提交事务
- 回滚未提交事务
如果已经回滚了未提交事务,那么就无法再应用增量备份。
在 mariadb 10.0 上测试发现不加--redo-only预备全备,然后使用--redo-only应用增量备份,MySQL 服务能够正常启动并且数据被成功 还原在全备上,使用--redo-only只做已提交事务,不回滚未提交事务innobackupex --apply-log --redo-only BASE-DIR
-
应用第一个增量备份
innobackupex --apply-log --redo-only BASE-DIR --incremental-dir=INCREMENTAL-DIR-1如果没有指定
--incremental-dir,那么 innobackupex 会使用最近的一个在 basedir 中被创建的子目录。 -
应用另外一个备份
innobackupex --apply-log BASE-DIR --incremental-dir=INCREMENTAL-DIR-2因为是最后一个增量备份所以没有必要再加
--redo-only,这样最后一个增量也被应用到全备上了。--redo-only除了最后一个不用加之外,其他的增量应用都要加,最后一个应用的时候可以直接进入回滚未提交事务阶段。如果加了也没事,服务启动的 时候会进入 recovery 过程,来回滚。 需要注意的是,应用增量备份的时候只能按照备份的顺序来应用。如果应用顺序错误,那么备份就不可用。如果无法确定顺序, 可以使用xtrabackup-checkpoints来确定顺序。 -
回滚未提交事务
当应用完所有增量备份的时候,就需要回滚所有为完成事务(如果最后一步加了--redo-only就需要回滚未提交,不执行的话在服务启动阶段服务会 处理未提交事务)。innobackupex --apply-log BASE-DIRNote 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* 文件,与文中提到不符。
还原增量备份
还原增量备份其实和还原全备一样
innobackupex --copy-back BASE-DIR
注意事项可以看:使用 innobackupex 还原备份
可以使用流(stream)做增量备份
-
先进行一个全备
shell innobackupex /data/backups -
备份本地
innobackupex --incremental --incremental-lsn=LSN-number --stream=xbstream ./ > incremental.xbstream- 解包方法
xbstream -x < incremental.xbstream
- 解包方法
-
使用本地备份流到远程并解包
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 | 正则匹配表名模式 | 按命名规则筛选少量表 |
--tables-file | 从文件读取表列表 | 需要备份的表数量多、批量管理 |
--databases | 指定数据库列表 | 按数据库/表粒度精确指定 |
注意:
--databases只影响非 InnoDB 表(如 MyISAM),InnoDB 数据文件总是全量备份。选错选项可能导致备份范围不符预期。
1. --include — 正则匹配
通过正则表达式匹配需要备份的表名,底层传给 xtrabackup 的 --tables 参数。
所有数据库目录都会被创建,但未匹配到表的目录为空。
innobackupex --include='^mydatabase[.]mytable' /path/to/backup
2. --tables-file — 文件列表
从文本文件读取要备份的表列表,每行一个 database.table。
底层传给 xtrabackup 的 --tables-file 参数。只有匹配到表的数据库目录才会被创建,比 --include 更干净。
echo "mydatabase.mytable" > /tmp/tables.txt
innobackupex --tables-file=/tmp/tables.txt /path/to/backup
3. --databases — 数据库列表
直接指定数据库和表,格式为 database_name[.tablename],空格分隔多个。
innobackupex --databases="mydatabase.mytable mysql" /path/to/backup
警告:
--databases对 InnoDB 无效!即使只指定一个表,所有 InnoDB 数据文件仍会被全量备份。如需真正按表粒度备份 InnoDB,请使用--include或--tables-file。
预备部分备份
部分备份的预备需要使用 --export:
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;
2. Discard 表空间
ALTER TABLE mydatabase.mytable DISCARD TABLESPACE;
之后把文件复制到相应的目录下(注意文件的所有者和文件权限),需要的文件:
.ibd— 表空间数据文件(必须).exp— 导出文件(Percona Server).cfg— 表结构验证文件(MySQL 5.6+)
3. Import 表空间
ALTER TABLE mydatabase.mytable IMPORT TABLESPACE;
窄备份
窄备份指不备份 secondary 索引数据,可以减少备份大小。缺点是需要重建索引,会很慢。
创建窄备份
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 重新创建索引:
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选项
innobackupex --stream=tar /tmp
innobackupex 会用子程序启动 xtrabackup --log-stream 定向到临时文件,然后使用 xbstream 把所有数据文件 stream 到 STDOUT。
当压缩启动,xtrabackup 压缩所有输出数据,但是元数据和非 innodb 文件不能被压缩。现在唯一支持的压缩算法是 quicklz。会生产 qpress 归档
格式的文件。
使用 xbstream 可以平法复制压缩可以提高备份速度。
-
使用 xbstream 流备份
innobackupex --stream=xbstream /root/backup/ > /root/backup/backup.xbstream -
使用流压缩
innobackupex --stream=xbstream --compress /root/backup/ > /root/backup/backup.xbstream -
解包
bstream -x < backup.xbstream -C /root/backup/ -
流压缩并备份到另外一台机器
innobackupex --compress --stream=xbstream /root/backup/ | ssh user@otherhost "xbstream -x -C /root/backup/" -
使用 tar 备份
innobackupex --stream=tar /root/backup/ > /root/backup/out.tar -
使用 tar 流并备份到其他服务器
innobackupex --stream=tar ./ | ssh user@destination \ "cat - > /data/backups/backup.tar" -
提取 tar 流,需要加 i 参数
tar -xizf backup.tar.gz -
也可以压缩流
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 备份文件的线程数。
innobackupex --parallel=4 /path/to/backup
-
使用 xbstream
可以考虑通过--compress-threads加速压缩进程,默认为 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选项:innobackupex --apply-log --export /path/to/backup会在发现多了一个 .exp 文件和 .cfg 文件(用于不同的 MySQL 版本)
find /data/backups/MySQL/ -name export_test.* -
导入表
先创建一个表,表结构需要和被还原的一样。CREATE TABLE mytable (...) ENGINE=InnoDB; -
discard 表空间
ALTER TABLE mydatabase.mytable DISCARD TABLESPACE;之后把文件复制到相应的目录下(注意文件的所有者和文件权限),需要文件 .ibd,.exp 或者 .cfg 文件(.cfg 文件用户 MySQL5.6)。
-
import 表空间
ALTER TABLE mydatabase.mytable IMPORT TABLESPACE;
时间点还原
和 MySQL 手册中介绍的时间点还原一样,xtrabackup 也是通过 binary log 进行时间点还原。
-
先进行备份
innobackupex /path/to/backup --no-timestamp -
进行预备
innobackupex --apply-log /path/to/backup -
在服务器中找出操作 binary log 和当前 binary log 状态
# 查看binary log SHOW BINARY LOGS;