MySQL经常使用备份策略详解 —— mysqldump、mysqlpump 和 Xtrabackup

1、备份简介

2.1 备份分类

按照不一样的思考维度,一般将数据库的备份分为如下几类:html

物理备份 与 逻辑备份mysql

  • 物理备份:备份的是完整的数据库目录和数据文件。采用该模式会进行大量的 IO 操做,但不含任何逻辑转换,所以备份和恢复速度一般都比较快。
  • 逻辑备份:经过数据库结构和内容信息来进行备份。由于要执行逻辑转换,所以其速度较慢,而且在以文本格式保存时,其输出文件的大小大于物理备份。逻辑备份的还原的粒度能够从服务器级别(全部数据库)精确到具体表,但备份不会包括日志文件、配置文件等与数据库无关的内容。

全量备份 与 增量备份git

  • 全量备份:备份服务器在给定时间点上的全部数据。
  • 增量备份:备份在给定时间跨度内(从一个时间点到另外一个时间点)对数据所作的更改。

在线备份 与 离线备份github

  • 在线备份:数据库服务在运行状态下进行备份。此时其余客户端依旧能够链接到数据库,但为了保证数据的一致性,在备份期间可能会对数据进行加锁,此时客户端的访问依然会受限。
  • 离线备份:在数据库服务停机状态下进行备份。此备份过程简单,但因为没法提供对外服务,一般会对业务形成比较大的影响。

2.2 备份工具

MySQL 支持的备份工具备不少种,这里列出经常使用的三种:算法

  • mysqldump:这是 MySQL 自带的备份工具,其采用的备份方式是逻辑备份,支持全库备份、单库备份、单表备份。因为其采用的是逻辑备份,因此生成的备份文件比物理备份的大,且所需恢复时间也比较长。
  • mysqlpump:这是 MySQL 5.7 以后新增的备份工具,在 mysqldump 的基础上进行了功能的扩展,支持多线程备份,支持对备份文件进行压缩,可以提升备份的速度和下降备份文件所需的储存空间。
  • Xtrabackup:这是 Percona 公司开发的实时热备工具,可以在不停机的状况下进行快速可靠的热备份,而且备份期间不会间断数据库事务的处理。它支持数据的全备和增备,而且因为其采用的是物理备份的方式,因此恢复速度比较快。

2、mysqldump

2.1 经常使用参数

mysqldump 的基本语法以下:sql

# 备份数据库或数据库中的指定表
mysqldump [options] db_name [tbl_name ...]
# 备份多个指定的数据库
mysqldump [options] --databases db_name ...
# 备份当前数据库实例中的全部表
mysqldump [options] --all-databases
复制代码

options 表明可选操做,经常使用的可选参数以下:shell

  • --host=host_name, -h host_name数据库

    指定服务器地址。缓存

  • --user=user_name, -u user_namebash

    指定用户名。

  • --password[=password], -p[password]

    指定密码。一般无需在命令行中明文指定,按照提示输入便可。

  • --default-character-set=charset_name

    导出文本使用的字符集,默认为 utf8。

  • --events, -E

    备份包含数据库中的事件。

  • --ignore-table=db_name.tbl_name

    不须要进行备份的表,必须使用数据库和表名来共同指定。也能够做用于视图。

  • --routines, -R

    备份包含数据库中的存储过程和自定义函数。

  • --triggers

    备份包含数据库中的触发器。

  • --where='where_condition', -w 'where_condition'

    在对单表进行导出时候,能够指定过滤条件,例如指定用户名 --where="user='jimf'" 或用户范围 -w"userid>1"

  • --lock-all-tables, -x

    锁定全部数据库中的全部表,从而保证备份数据的一致性。此选项自动关闭 --single-transaction--lock-tables

  • --lock-tables, -l

    锁定当前数据库中全部表,可以保证当前数据库中表的一致性,但不能保证全局的一致性。

  • --single-transaction

    此选项会将事务隔离模式设置为 REPEATABLE READ 并开启一个事务,从而保证备份数据的一致性。主要用于事务表,如 InnoDB 表。 可是此时仍然不能在备份表上执行 ALTER TABLE, CREATE TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE 等操做,由于 REPEATABLE READ 并不能隔离这些操做。

    另外须要注意的是 --single-transaction 选项与 --lock-tables 选项是互斥的,由于 LOCK TABLES 会致使任何正在挂起的事务被隐式提交。转储大表时,能够将 --single-transaction 选项与 --quick 选项组合使用 。

  • --quick, -q

    主要用于备份大表。它强制 mysqldump 一次只从服务器检索一行数据,避免一次检索全部行而致使缓存溢出。

  • --flush-logs, -F

    在开始备份前刷新 MySQL 的日志文件。此选项须要 RELOAD 权限。若是此选项与 --all-databases 配合使用,则会在每一个数据库开始备份前都刷新一第二天志。若是配合 --lock-all-tables--master-data--single-transaction 使用,则只会在锁定全部表或者开启事务时刷新一次。

  • --master-data[=value]

    能够经过配置此参数来控制生成的备份文件是否包含 CHANGE MASTER 语句,该语句中包含了当前时间点二进制日志的信息。该选项有两个可选值:1 和 2 ,设置为 1 时 CHANGE MASTER 语句正常生成,设置为 2 时以注释的方式生成。--master-data 选项还会自动关闭 --lock-tables 选项,并且若是你没有指定 --single-transaction 选项,那么它还会启用 --lock-all-tables 选项,在这种状况下,会在备份开始时短暂内获取全局读锁。

2.2 全量备份

mysqldump 的全量备份与恢复的操做比较简单,示例以下:

# 备份雇员库
mysqldump  -uroot -p --databases employees > employees_bak.sql
 # 恢复雇员库
mysql -uroot -p  < employees_bak.sql
复制代码

单表备份:

# 备份雇员库中的职位表
mysqldump  -uroot -p --single-transaction employees titles > titles_bak.sql
 # 恢复雇员库中的职位表
mysql> use employees;
mysql> source /root/mysqldata/titles_bak.sql;
复制代码

2.3 增量备份

mysqldump 自己并不能直接进行增量备份,须要经过分析二进制日志的方式来完成。具体示例以下:

1. 基础全备

1.先执行一次全备做为基础,这里以单表备份为例,须要用到上文提到的 --master-data 参数,语句以下:

mysqldump -uroot -p --master-data=2 --flush-logs employees titles > titles_bak.sql
复制代码

使用 more 命令查看备份文件,此时能够在文件开头看到 CHANGE MASTER 语句,语句中包含了二进制日志的名称和偏移量信息,具体以下:

-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=155;
复制代码

2. 增量恢复

对表内容进行任意修改,而后经过分析二进制日志文件来生成增量备份的脚本文件,示例以下:

mysqlbinlog --start-position=155 \
--database=employees  ${MYSQL_HOME}/data/mysql-bin.000004 > titles_inr_bak_01.sql
复制代码

须要注意的是,在实际生产环境中,可能在全量备份后与增量备份前的时间间隔里生成了多份二进制文件,此时须要对每个二进制文件都执行相同的命令:

mysqlbinlog --database=employees  ${MYSQL_HOME}/data/mysql-bin.000005 > titles_inr_bak_02.sql
mysqlbinlog --database=employees  ${MYSQL_HOME}/data/mysql-bin.000006 > titles_inr_bak_03.sql
.....
复制代码

以后将全备脚本 ( titles_bak.sql ),以及全部的增备脚本 ( inr_01.sql,inr_02.sql .... ) 经过 source 命令导入便可,这样就完成了全量 + 增量的恢复。

3、mysqlpump

3.1 功能优点

mysqlpump 在 mysqldump 的基础上进行了扩展加强,其主要的优势以下:

  • 可以并行处理数据库及其中的对象,从而能够加快备份进程;

  • 可以更好地控制数据库及数据库对象(表,存储过程,用户账户等);

  • 可以直接对备份文件进行压缩;

  • 备份时可以显示进度指标(估计值);

  • 备份用户时生成的是 CREATE USER 与 GRANT 语句,而不是像 mysqldump 同样备份成数据,能够方便用户按需恢复。

3.2 经常使用参数

mysqlpump 的使用和 mysqldump 基本一致,这里再也不进行赘述。如下主要介绍部分新增的可选项,具体以下:

  • --default-parallelism=N

    每一个并行处理队列的默认线程数。默认值为 2。

  • --parallel-schemas=[N:]db_list

    用于并行备份多个数据库:db_list 是一个或多个以逗号分隔的数据库名称列表;N 为使用的线程数,若是没有设置,则使用 --default-parallelism 参数的值。

  • --users

    将用户信息备份为 CREATE USER 语句和 GRANT 语句 。若是想要只备份用户信息,则可使用下面的命令:

    mysqlpump --exclude-databases=% --users
    复制代码
  • --compress-output=algorithm

    默认状况下,mysqlpump 不对备份文件进行压缩。可使用该选项指定压缩格式,当前支持 LZ4 和 ZLIB 两种格式。须要注意的是压缩后的文件能够占用更少的存储空间,可是却不能直接用于备份恢复,须要先进行解压,具体以下:

    # 采用lz4算法进行压缩
    mysqlpump --compress-output=LZ4 > dump.lz4
    # 恢复前须要先进行解压
    lz4_decompress input_file output_file
     # 采用ZLIB算法进行压缩
    mysqlpump --compress-output=ZLIB > dump.zlib
    zlib_decompress input_file output_file
    复制代码

    MySQL 发行版自带了上面两个压缩工具,不须要进行额外安装。以上就是 mysqlpump 新增的部分经常使用参数,完整参数能够参考官方文档:mysqlpump — A Database Backup Program

4、Xtrabackup

4.1 在线安装

Xtrabackup 能够直接使用 yum 命令进行安装,这里个人 MySQL 为 8.0 ,对应安装的 Xtrabackup 也为 8.0,命令以下:

# 安装Percona yum 源
yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpm
 # 安装
yum install percona-xtrabackup-80
复制代码

4.2 全量备份

全量备份的具体步骤以下:

1. 建立备份

Xtrabackup 全量备份的基本语句以下,可使用 target-dir 指明备份文件的存储位置,parallel 则是指明操做的并行度:

xtrabackup --backup  --user=root --password --parallel=3  --target-dir=/data/backups/
复制代码

以上进行的是整个数据库实例的备份,若是须要备份指定数据库,则可使用 --databases 进行指定。

另一个容易出现的异常是:Xtrabackup 在进行备份时,默认会去 /var/lib/mysql/mysql.sock 文件里获取数据库的 socket 信息,若是你修改了数据库的 socket 配置,则须要使用 --socket 参数进行从新指定,不然会抛出找不到链接的异常。备份完整后须要当即执行的另一个操做是 prepare (准备备份)。

2. 准备备份

因为备份是将全部物理库表等文件复制到备份目录,而整个过程须要持续一段时间,此时备份的数据中就可能会包含还没有提交的事务或已经提交但还没有同步至数据文件中的事务,最终致使备份结果处于不一致状态。此时须要进行 prepare 操做来回滚未提交的事务及同步已经提交的事务至数据文件,从而使得总体达到一致性状态。命令以下:

xtrabackup --prepare --target-dir=/data/backups/
复制代码

须要特别注意的在该阶段不要随意中断 xtrabackup 进程,由于这可能会致使数据文件损坏,备份将没法使用。

3. 恢复备份

因为 xtrabackup 执行的是物理备份,因此想要进行恢复,必须先要中止 MySQL 服务。同时这里咱们能够删除 MySQL 的数据目录来模拟数据丢失的状况,以后使用如下命令将备份文件拷贝到 MySQL 的数据目录下:

# 模拟数据异常丢失
rm -rf /usr/app/mysql-8.0.17/data/*
 # 将备份文件拷贝到 data 目录下
xtrabackup --copy-back --target-dir=/data/backups/
复制代码

copy-back 命令只须要指定备份文件的位置,不须要指定 MySQL 数据目录的位置,由于 Xtrabackup 会自动从 /etc/my.cnf 上获取 MySQL 的相关信息,包括数据目录的位置。若是不须要保留备份文件,能够直接使用 --move-back 命令,表明直接将备份文件移动到数据目录下。此时数据目录的全部者一般为执行命令的用户,须要更改成 mysql 用户,命令以下:

chown -R mysql:mysql /usr/app/mysql-8.0.17/data
复制代码

再次启动便可完成备份恢复。

4.3 增量备份

使用 Xtrabackup 进行增量备份时,每一次增量备份都须要以上一次的备份为基础,以后再将增量备份运用到第一次全备之上,从而完成备份。具体操做以下:

1. 建立备份

这里首先建立一个全备做为基础:

xtrabackup  --user=root --password --backup  --target-dir=/data/backups/base/
复制代码

以后修改库中任意数据,而后进行第一次增量备份,此时须要使用 incremental-basedir 指定基础目录为全备目录:

xtrabackup  --user=root --password --backup  --target-dir=/data/backups/inc1 \
--incremental-basedir=/data/backups/base
复制代码

再修改库中任意数据,而后进行第二次增量备份,此时须要使用 incremental-basedir 指定基础目录为上一次增备目录:

xtrabackup  --user=root --password --backup  --target-dir=/data/backups/inc2 \
--incremental-basedir=/data/backups/inc1
复制代码

2. 准备备份

准备基础备份:

xtrabackup --prepare --apply-log-only --target-dir=/data/backups/base
复制代码

将第一次备份做用于全备数据:

xtrabackup --prepare --apply-log-only --target-dir=/data/backups/base \
--incremental-dir=/data/backups/inc1
复制代码

将第二次备份做用于全备数据:

xtrabackup --prepare --target-dir=/data/backups/base \
--incremental-dir=/data/backups/inc2
复制代码

在准备备份时候,除了最后一次增备外,其他的准备命令都须要加上 --apply-log-only 选项来阻止事务的回滚,由于备份时未提交的事务可能正在进行,并可能在下一次增量备份中提交,若是不进行阻止,那么增量备份将没有任何意义。

3. 恢复备份

恢复备份和全量备份时相同,只须要最终准备好的全备数据复制到 MySQL 的数据目录下便可:

xtrabackup --copy-back --target-dir=/data/backups/base
# 必须修改文件权限,不然没法启动
chown -R mysql:mysql /usr/app/mysql-8.0.17/data
复制代码

此时增量备份就已经完成。须要说明的是:按照上面的状况,若是第二次备份以后发生了宕机,那么第二次备份后到宕机前的数据依然无法经过 Xtrabackup 进行恢复,此时就只能采用上面介绍的分析二进制日志的恢复方法。由此能够看出,不管是采用何种备份方式,二进制日志都是很是重要的,所以最好对其进行实时备份。

5、二进制日志的备份

想要备份二进制日志文件,能够经过定时执行 cp 或 scp 等命令来实现,也能够经过 mysqlbinlog 自带的功能来实现远程备份,将远程服务器上的二进制日志文件复制到本机,命令以下:

mysqlbinlog --read-from-remote-server --raw --stop-never \
--host=主机名 --port=3306 \
--user=用户名 --password=密码  初始复制时的日志文件名
复制代码

须要注意的是这里的用户必须具备 replication slave 权限,由于上述命令本质上是模拟主从复制架构下,从节点经过 IO 线程不断去获取主节点的二进制日志,从而达到备份的目的。

参考资料

更多文章,欢迎访问 [全栈工程师手册] ,GitHub 地址:github.com/heibaiying/…

相关文章
相关标签/搜索