• MySQL备份与恢复工具之XTRABACKUP


    Percona XtraBackup是一款开源的MySQL热备份工具。XtraBackup支持对基于InnoDB、XtraDB和MyISAM存储引擎的表的备份,且支持Oracle MySQL、Percona Server和MariaDB多个分支。目前官网提供2.4和8.0两个版本的下载,前者支持MySQL 5.1、5.5、5.6、5.7的备份,后者仅支持MySQL 8.0的备份。

    ☕️ 安装

    XtraBackup的下载地址为:https://www.percona.com/downloads/Percona-XtraBackup-2.4/Percona-XtraBackup-2.4.24/binary/redhat/7/x86_64/

    安装xtrabackup

    提前下好tar安装包,使用yum localinstall安装自动解决安装包依赖问题:

    [root@mysql-node1 ~]# tar -xvf Percona-XtraBackup-2.4.24-rb4ee263-el7-x86_64-bundle.tar
    [root@mysql-node1 ~]# yum localinstall -y percona-xtrabackup-24-2.4.24-1.el7.x86_64.rpm
    
    • 1
    • 2

    如果使用rpm命令安装,需要手动安装依赖:

    yum install -y perl-DBD-MySQL per-DBI perl-Time-HiRes libaio*
    yum install -y perl-Digest-MD5 rsync
    yum install -y libev
    rpm -ivh percona-xtrabackup-24-2.4.24-1.el7.x86_64.rpm
    
    • 1
    • 2
    • 3
    • 4

    安装压缩备份工具qpress

    [root@mysql-node1 ~]# wget https://repo.percona.com/yum/release/7/RPMS/x86_64/qpress-11-1.el7.x86_64.rpm
    [root@mysql-node1 ~]# yum localinstall qpress-11-1.el7.x86_64.rpm -y
    
    • 1
    • 2

    🐾 原理

    安装XtraBackup后会在/usr/bin下生成四个可执行文件:innobackupex、xtrabackup、xbcrypt、xbstream。其中,innobackupex用于备份非InnoDB引擎的表,同时还会调用xtrabackup备份InnoDB表。innobackupex还可以与MySQL Server进行交互,比如加读锁(FTWRL)、获取主从同步位点(show slave status)等。xbcrypt和xbstream分别用于备份恢复过程中的加解密和并发写支持。

    👁 注意:XtraBackup 2.3版本用C语言对innobackupex进行了重写,所以2.3和2.4版本的innobackupex实际上是xtrabackup的一个软链接。

    XtraBackup备份实现基于InnoDB存储引擎的故障恢复功能(crash-recovery)。也就是说,xtrabackup备份的数据最开始是不满足一致性的,但是通过模拟redo log故障恢复的过程最终能够获取到满足一致性的备份数据。

    XtraBackup备份的流程大致如下:

    1. innonackupex进程会fork一个xtrabackup子进程,用于备份InnoDB表。
    2. xtrabackup进程会产生一个redo拷贝线程和一个ibd拷贝线程。Redo拷贝线程会记录备份开始时刻redo log中的日志序列号(LSN),并备份redo日志。ibd拷贝线程负责备份ibd数据文件。
    3. InnoDB表备份完成后,ibd拷贝线程退出。
    4. innobackupex进程执行flush tables with read lock加全局读锁。如果数据库是Percona Server,则会执行lock tables for backup加一个轻量的备份锁(Backup locks)。这里只会给MyISAM和其他非InnoDB表加备份锁,目的是为了避免在备份非InnoDB表的过程中阻塞修改InnoDB表的DML操作。
    5. innobackupex进程开始备份非InnoDB表和数据库文件。备份的文件后缀包括.frm.MRG.MYD.MYI.TRG.TRN.ARM.ARZ.CSM.CSV.par.opt
    6. 非InnoDB表备份完成后,innobackupex进程执行lock binlog for backup,以避免binlog一致性位点(Exec_Master_Log_Pos或者Exec_Gtid_Set)被修改。随后xtrabackup进程完成redo log备份,并通过执行show master|slave status取得binlog一致性位点。
    7. innobackupex进程移除FTWRL全局读锁(或者备份锁)、binlog锁。
    8. xtrabackup进程退出,备份结束。

    在上面的备份流程中,XtraBackup是通过直接读取操作系统文件来进行备份的,只有在执行SQL命令时会和数据库有少量交互,基本对数据库运行无影响。只有在备份非InnoDB表的时候会处于短时间的只读状态(取决于MyISAM表的数据量,一般在几秒左右)。

    🦌 用法

    全量备份与还原

    STEP 1: BACKUP

    将全量备份导出到/backup目录下,并将错误日志输出到backup.log中。

    XtraBackup备份和还原时会从配置文件/etc/my.cnf中读取datadirinnodb_data_home_dirinnodb_data_file_pathinnodb_log_group_home_dir变量。如果没有定义,则会报错Missing argument。

    [root@mysql-node1 ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=ABCcba123 \
    /backup 2> /backup/backup.log
    [root@mysql-node1 backup]# cat backup.log
    xtrabackup: recognized server arguments: --datadir=/mysql/data --server-id=142 --log_bin=/mysql/log/mysql-bin --innodb_io_capacity=500 --innodb_flush_method=O_DIRECT --innodb_log_file_size=1G --innodb_file_per_table=1 --innodb_buffer_pool_size=3G --innodb_data_file_path=ibdata1:512M:autoextend --innodb_autoextend_increment=64 --innodb_checksum_algorithm=crc32 --innodb_read_io_threads=4 --innodb_log_buffer_size=8388608 --innodb_write_io_threads=4 --innodb_flush_log_at_trx_commit=1 --tmpdir=/mysql/tmp
    220912 01:57:45 innobackupex: Missing argument
    [root@mysql-node1 backup]#
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    如果没有定义这些变量,需要在备份命令中手动指定。其中,innodb_data_home_dirinnodb_log_group_home_dir如果没有在配置文件中定义,默认会与datadir相同。

    [root@mysql-node1 backup]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=ABCcba123 \
    --innodb_data_home_dir=/mysql/data --innodb_log_group_home_dir=/mysql/data  /backup 2> /backup/backup.log
    [root@mysql-node1 backup]#
    [root@mysql-node1 backup]# cat backup.log
    xtrabackup: recognized server arguments: --datadir=/mysql/data --server-id=142 --log_bin=/mysql/log/mysql-bin --innodb_io_capacity=500 --innodb_flush_method=O_DIRECT --innodb_log_file_size=1G --innodb_file_per_table=1 --innodb_buffer_pool_size=3G --innodb_data_file_path=ibdata1:512M:autoextend --innodb_autoextend_increment=64 --innodb_checksum_algorithm=crc32 --innodb_read_io_threads=4 --innodb_log_buffer_size=8388608 --innodb_write_io_threads=4 --innodb_flush_log_at_trx_commit=1 --tmpdir=/mysql/tmp --innodb_data_home_dir=/mysql/data --innodb_log_group_home_dir=/mysql/data
    xtrabackup: recognized client arguments:
    220912 02:09:28 innobackupex: Starting the backup operation
    
    IMPORTANT: Please check that the backup run completes successfully.
               At the end of a successful backup run innobackupex
               prints "completed OK!".
    
    220912 02:09:28  version_check Connecting to MySQL server with DSN 'dbi:mysql:;mysql_read_default_group=xtrabackup' as 'root'  (using password: YES).
    Failed to connect to MySQL server: DBI connect(';mysql_read_default_group=xtrabackup','root',...) failed: Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2) at - line 1314.
    220912 02:09:28 Connecting to MySQL server host: localhost, user: root, password: set, port: not set, socket: not set
    Failed to connect to MySQL server: Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2).
    [root@mysql-node1 backup]#
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    如果datadir不是默认的/var/lib/mysql,则还需要指定mysql.sock的文件路径,否则会报错数据库连接失败。

    [root@mysql-node1 backup]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=ABCcba123 \
    --innodb_data_home_dir=/mysql/data --innodb_log_group_home_dir=/mysql/data  \
    --socket=/tmp/mysql.sock /backup 2> /backup/backup.log
    [root@mysql-node1 backup]#
    [root@mysql-node1 backup]# ls /backup
    2022-09-12_02-17-32  backup.log
    [root@mysql-node1 backup]# ls /backup/2022-09-12_02-17-32/
    appgame        ib_buffer_pool  mysql               sys                     xtrabackup_checkpoints  xtrabackup_logfile
    backup-my.cnf  ibdata1         performance_schema  xtrabackup_binlog_info  xtrabackup_info
    [root@mysql-node1 backup]#
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    👁 注意:备份命令innobackupex ... /backup也可以替换为xtrabackup ... --target-dir=/backup --backup

    STEP 2: PREPARE

    假设我们不小心把应用库删了:

    mysql> drop database appgame;
    Query OK, 1 row affected (0.01 sec)
    
    • 1
    • 2

    由于备份文件中的InnoDB数据在时间点上是不一致的,因此不能直接用于恢复数据。在利用备份文件进行恢复前,需要先进行Prepare。PREPARE会模仿InnoDB crash-recovery的过程,将备份数据还原到一个一致性位点。

    [root@mysql-node1 backup]# xtrabackup --prepare --target-dir=/backup/2022-09-12_02-17-32/
    ...
    InnoDB: Starting shutdown...
    InnoDB: Shutdown completed; log sequence number 2806312
    220912 03:26:36 completed OK!
    
    • 1
    • 2
    • 3
    • 4
    • 5

    出现以上信息则表示PREPARE完成。PREPARE过程中不能中断xtrabackup进程,否则有可能导致数据损坏,使得备份不可用。

    STEP 3: RESTORE

    利用备份还原数据库之前,必须满足以下三个条件:

    • 已经对备份数据进行PREPARE;
    • MySQL Server服务已经停止(systemctl stop mysqld);
    • MySQL数据目录datadir必须是空目录(rm -rf /mysql/data/*)。

    可以通过以下三种方法还原数据库:

    • copy-back:保留原有的备份文件;
    • move-back:将备份文件移动到MySQL数据目录下;
    • rsync或cp:直接通过操作系统命令拷贝备份文件。例如:
      rsync -avrP /backup/2022-09-12_02-17-32/ /mysql/data/

    使用copy-back方法还原数据库:

    [root@mysql-node1 backup]# xtrabackup --copy-back --target-dir=/backup/2022-09-12_02-17-32/
    
    • 1

    修改datadir权限并启动MySQL数据库服务:

    [root@mysql-node1 backup]# chown -R mysql:mysql /mysql/data
    [root@mysql-node1 backup]#
    [root@mysql-node1 backup]# systemctl start mysqld
    
    • 1
    • 2
    • 3

    增量备份与还原

    XtraBackup仅支持对InnoDB表进行增量备份,所以MyISAM表每次都是全量备份。

    STEP 1: BACKUP

    在进行增量备份之前必须做一次全量备份,且全量备份的存放路径以base结尾:

    [root@mysql-node1 backup]# mkdir base
    [root@mysql-node1 backup]# xtrabackup --defaults-file=/etc/my.cnf --user=root --password=ABCcba123 \
    --innodb_data_home_dir=/mysql/data --innodb_log_group_home_dir=/mysql/data  \
    --socket=/tmp/mysql.sock --target-dir=/backup/base --backup 2> /backup/backup.log
    
    • 1
    • 2
    • 3
    • 4

    创建一张新表,并插入数据:

    mysql> create table `brands` (
        -> `id` int not null,
        -> `name` varchar(30) not null,
        -> `country` varchar(20),
        -> `celebrity` varchar(30),
        -> primary key pk_id(id)
        -> ) engine=InnoDB default charset=utf8mb4;
    Query OK, 0 rows affected (0.01 sec)
    
    ...
    mysql> select * from brands;
    +----+--------------+---------+---------------+
    | id | name         | country | celebrity     |
    +----+--------------+---------+---------------+
    |  1 | Nike         | America | Lebron James  |
    |  2 | Under Armour | America | Stephen Curry |
    |  3 | Anta         | China   | Klay Thompson |
    |  4 | Adidas       | Germany | Derrick Rose  |
    |  5 | Lining       | China   | Jimmy Butler  |
    +----+--------------+---------+---------------+
    5 rows in set (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    进行增量备份时,通过--incremental-basedir参数指定上一次备份的存放路径。

    进行第一次增量备份,保存到/backup/inc1路径下:

    [root@mysql-node1 backup]# xtrabackup --backup --user=root --password=ABCcba123 \
    --innodb_data_home_dir=/mysql/data --innodb_log_group_home_dir=/mysql/data  \
    --socket=/tmp/mysql.sock --target-dir=/backup/inc1 --incremental-basedir=/backup/base 2> /backup/backup.log
    
    • 1
    • 2
    • 3

    进行第二次增量备份,保存到/backup/inc2路径下:

    [root@mysql-node1 backup]# xtrabackup --backup --user=root --password=ABCcba123 \
    --innodb_data_home_dir=/mysql/data --innodb_log_group_home_dir=/mysql/data  \
    --socket=/tmp/mysql.sock --target-dir=/backup/inc2 --incremental-basedir=/backup/inc1 2> /backup/backup.log
    
    • 1
    • 2
    • 3

    ⚠️ 注意--incremental-basedir对应上一次备份的存放路径。

    STEP 2: PREPARE

    在对全量备份做PREPARE时,未提交的事务会被rollback。考虑到这些事务可能会在增量备份时提交,因此对于会追加增量备份的每一次备份,在做PREPARE时必须跳过rollback的环节。这里可以通过在最后一次备份之前的所有备份PREPARE时加上--apply-log-only参数实现。

    Prepare全量备份:

    xtrabackup --prepare --apply-log-only --target-dir=/backup/base
    
    • 1

    Prepare第一次增量备份:

    xtrabackup --prepare --apply-log-only --target-dir=/backup/base --incremental-dir=/backup/inc1
    
    • 1

    Prepare第二次增量备份:

    xtrabackup --prepare --target-dir=/backup/base --incremental-dir=/backup/inc2
    
    • 1

    ⚠️ 注意

    1. 按照备份顺序依次Prepare增量备份,并且target-dir一直都是全量备份路径,包括在最后还原数据库时copy-back的也是/backup/base
    2. 最后一次Prepare增量备份时,要加--apply-log-only参数。

    STEP 3: RESTORE

    还原备份前,一定要停止数据库服务,并清空MySQL数据目录。

    使用copy-back方法还原数据库:

    [root@mysql-node1 backup]# xtrabackup --copy-back --target-dir=/backup/base
    
    • 1

    修改datadir权限并启动MySQL数据库服务:

    [root@mysql-node1 backup]# chown -R mysql:mysql /mysql/data
    [root@mysql-node1 backup]#
    [root@mysql-node1 backup]# systemctl start mysqld
    
    • 1
    • 2
    • 3

    References
    【1】https://docs.percona.com/percona-xtrabackup/2.4/index.html
    【2】https://docs.percona.com/percona-xtrabackup/2.4/how_xtrabackup_works.html
    【3】http://mysql.taobao.org/monthly/2016/03/07/
    【4】https://docs.percona.com/percona-xtrabackup/2.4/backup_scenarios/full_backup.html
    【5】https://docs.percona.com/percona-xtrabackup/2.4/backup_scenarios/incremental_backup.html#

  • 相关阅读:
    使用GetX实现GetPage中间件
    前端基建——前端团队技术构建方向指引
    JavaScript中常用对象方法总结
    国企秋招经验总结
    HOW - Lodash 使用指南和源码学习
    轻松掌握组件启动之MongoDB(下):高可用复制集架构环境搭建
    人工神经网络技术及应用,人工神经网络应用场景
    37.JavaScript对象与JSON格式的转换,JSON.stringify、JSON.parse方法的使用方法和注意事项
    PAT甲级--1035 Password
    python+vue+elementui学生选课作业系统wxjjv
  • 原文地址:https://blog.csdn.net/Sebastien23/article/details/126820058