MySQL增量备份实战指南

一、Xtrabackup基础与优势

1.1 Xtrabackup简介

Xtrabackup是一个开源的MySQL热备份工具,支持InnoDB、XtraDB存储引擎的在线备份,无需停止数据库服务即可完成数据拷贝。它分为两个组件:xtrabackup​(处理InnoDB/XtraDB表空间)和innobackupex​(封装脚本,支持MyISAM等表类型)。

1.2 增量备份原理

增量备份基于全量备份后的变更日志(如InnoDB的redo log),仅复制自上次备份以来修改过的数据页。Xtrabackup通过比较文件校验和或LSN(Log Sequence Number)识别变更,实现高效增量备份。

1.3 Xtrabackup优势

  • 非阻塞备份:在线备份,不影响业务运行。
  • 增量支持:显著减少备份时间和存储需求。
  • 压缩与加密:支持备份文件压缩和加密,增强安全性。
  • 跨平台兼容:支持Linux及Windows(需额外配置)。

二、增量备份前的准备工作

2.1 环境确认

  • MySQL版本:确保MySQL 5.6及以上,或Percona Server对应版本。(Xtrabackup推荐和MySQL版本一模一样)
  • 存储引擎:主要表使用InnoDB或XtraDB。
  • 磁盘空间:备份目录需有足够空间存放增量文件

2.2 安装Xtrabackup

  1. 更新软件包列表:在终端中运行以下命令以确保您的软件包列表是最新的:

    (版本要和MySQL的版本的一模一样)

    复制代码
    sudo apt update
  1. 安装XtraBackup:使用以下命令安装XtraBackup:

    复制代码
    # Ubuntu
    sudo apt install percona-xtrabackup-80
    
    # cenios
    wget https://downloads.percona.com/downloads/Percona-XtraBackup-8.4/Percona-XtraBackup-8.4.0-1/binary/redhat/7/x86_64/percona-xtrabackup-84-8.4.0-1.1.el7.x86_64.rpm
    
    yum -y install libev
    
    yum -y install perl-Digest-MD5
    
    yum install perl-DBD-MySQL -y
    
    yum install -y epel-release
    
    yum install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm
    percona-release enable-only tools release   # 只启用 tools 和 release 两个仓库
    yum clean all
    
    yum install -y ./percona-xtrabackup-84-8.4.0-1.1.el7.x86_64.rpm
  1. 验证安装:安装完成后,您可以使用以下命令检查XtraBackup的版本,以确认安装成功

    复制代码
    xtrabackup --version

三、全量备份、增量备份

3.1 要备份的数据

  1. 我们去单独设计一个脚本,模拟1000个用户数据

    (先单独创建一个test的库)

    复制代码
    #!/usr/bin/env bash
    DB_HOST="127.0.0.1"
    DB_PORT=3306
    DB_USER="root"
    DB_PWD="123"
    DB_NAME="test"
    TB_NAME="t_user"
    RECORDS=1000
    # 数据量,可以自定义的
    
    USER_ARR=(Alice Bob Carol Dave Eva Fred Gina Henry Iris Jack Kate Leo Mona Nick Olga Peter Quinn Rose Sammy Tina Uma Victor Wendy Xavier Yolanda Zoe)
    MOBILE_PREFIX=(130 131 132 133 134 135 136 137 138 139 150 151 152 153 155 156 157 158 159 170 171 172 173 174 175 176 177 178 180 181 182 183 184 185 186 187 188 189)
    
    rand_ip()    { printf "%d.%d.%d.%d" $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) ; }
    rand_user()  { echo "${USER_ARR[RANDOM%${#USER_ARR[@]}]}$((RANDOM%9000+1000))" ; }
    rand_mobile(){ echo "${MOBILE_PREFIX[RANDOM%${#MOBILE_PREFIX[@]}]}$((RANDOM%90000000+10000000))" ; }
    
    SQL="INSERT INTO $TB_NAME(ip,username,mobile) VALUES "
    for ((i=1;i<=RECORDS;i++)); do
      SQL+="('$(rand_ip)','$(rand_user)','$(rand_mobile)')"
      ((i<RECORDS)) && SQL+=","
    done
    mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PWD" "$DB_NAME" <<<"
    CREATE TABLE IF NOT EXISTS $TB_NAME(
      id       INT AUTO_INCREMENT PRIMARY KEY,
      ip       VARCHAR(15) NOT NULL,
      username VARCHAR(50) NOT NULL,
      mobile   CHAR(11)    NOT NULL,
      KEY idx_mobile(mobile)
    );
    $SQL;
    "
    
    echo "OK 添加 $RECORDS 数据到 $DB_NAME.$TB_NAME"
  1. 验证

    复制代码
    +------+-----------------+-------------+-------------+
    |    1 | 212.54.185.3    | Xavier9139  | 17510020394 |
    |    2 | 63.213.194.35   | Tina1623    | 15710011462 |
    |    3 | 5.32.136.84     | Dave8354    | 15010021720 |
    |    4 | 60.87.255.140   | Peter7920   | 13010030954 |
    |    5 | 134.159.124.74  | Tina3999    | 18710002815 |
    |    6 | 85.46.241.126   | Xavier6694  | 18410011074 |
    |    7 | 139.221.152.147 | Xavier9325  | 18410029894 |
    |    8 | 122.72.212.176  | Leo1702     | 13710017541 |
    |    9 | 242.2.44.145    | Jack7906    | 18310029171 |
    |   10 | 237.28.147.143  | Fred2537    | 18210023547 |
    |   11 | 31.149.72.54    | Alice2085   | 17410002319 |
    |   12 | 212.190.81.254  | Quinn9569   | 18710000674 |
    |   13 | 125.91.133.126  | Alice1473   | 15010014431 |
    |   14 | 90.122.97.60    | Eva5135     | 13010006979 |
    |   15 | 87.250.191.12   | Fred6919    | 15210031312 |

3.2 全量备份

  1. 要备份目录

    复制代码
    mkdir -p /home/backup/full
  1. 创建权限用户

    复制代码
    CREATE USER 'backup'@'localhost' IDENTIFIED BY 'Backup@123';
    GRANT RELOAD, LOCK TABLES, PROCESS, REPLICATION CLIENT, BACKUP_ADMIN ON *.* TO 'backup'@'localhost';
  1. 命令测试

    复制代码
    xtrabackup --defaults-file=/etc/my.cnf \
      --backup \
      --target-dir=/home/backup/full \
      --user=root \
      --password=123 \
      --host=127.0.0.1 \
      --port=3306
    
    
    --backup:备份
    --datadir:mysql文件目录
    --target-dir:要备份到的目录
    --user:数据库帐号
    --password:数据库密码
    --port:端口
    --host:IP
    --no-server-version-check:不检查mysql与percona-xtrabackup版本差别
    --defaults-file:指定上一步复制出来的my.cnf文件(安装在var/lib/mysql的可不加该参数)
  1. 检查

    复制代码
     ls /home/backup/full
    backup-my.cnf  ib_buffer_pool  mysql.ibd           sys       undo_002                xtrabackup_info         zabbix
    binlog.000006  ibdata1         performance_schema  test      xtrabackup_binlog_info  xtrabackup_logfile
    binlog.index   mysql           ry@002dvue          undo_001  xtrabackup_checkpoints  xtrabackup_tablespaces
  1. 恢复数据

    复制代码
    # 删除数据库(测试使用,真实环境想想就行的,不,想都不要想)
    drop database test;
    
    # 停止数据库
    systemctl stop mysqld
    
    # 将数据变成可恢复的数据
    xtrabackup --prepare --target-dir=/home/backup
    
    # (删除)源Data
    mv /usr/local/mysql/data/full /usr/local/mysql/data.bak
    
    # copy-back(真实恢复数据)
    xtrabackup --copy-back --target-dir=/home/backup/full
    
    # 修权限
    chown -R mysql:mysql /usr/local/mysql/data
    
    # MySQL
    systemctl start mysqld
  1. 验证

    复制代码
    mysql -u root -p123 -e "show databases;"
    mysql: [Warning] Using a password on the command line interface can be insecure.
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | ry-vue             |
    | sys                |
    | test               |
    | zabbix             |
    +--------------------+

3.2 增量备份

增量备份要基于全量备份

  1. 第一次全量备份

    复制代码
    xtrabackup --defaults-file=/etc/my.cnf \
      --backup \
      --target-dir=/home/backup/full \
      --user=root \
      --password=123 \
      --host=127.0.0.1 \
      --port=3306
  2. 使用脚本再添加新的数据(但其实,再执行上一个脚本就好了)

    复制代码
    #!/usr/bin/env bash
    
    DB_HOST="127.0.0.1"
    DB_PORT=3306
    DB_USER="root"
    DB_PWD="123"
    DB_NAME="test"
    TB_NAME="t_user"
    RECORDS=1000  # 新增数据条数
    
    USER_ARR=(Alice Bob Carol Dave Eva Fred Gina Henry Iris Jack Kate Leo Mona Nick Olga Peter Quinn Rose Sammy Tina Uma Victor Wendy Xavier Yolanda Zoe)
    MOBILE_PREFIX=(130 131 132 133 134 135 136 137 138 139 150 151 152 153 155 156 157 158 159 170 171 172 173 174 175 176 177 178 180 181 182 183 184 185 186 187 188 189)
    
    rand_ip()    { printf "%d.%d.%d.%d" $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) ; }
    rand_user()  { echo "${USER_ARR[RANDOM%${#USER_ARR[@]}]}$((RANDOM%9000+1000))" ; }
    rand_mobile(){ echo "${MOBILE_PREFIX[RANDOM%${#MOBILE_PREFIX[@]}]}$((RANDOM%90000000+10000000))" ; }
    
    MAX_ID=$(mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PWD" -N -B -e "SELECT IFNULL(MAX(id),0) FROM $DB_NAME.$TB_NAME;")
    
    SQL="INSERT INTO $TB_NAME(ip,username,mobile) VALUES "
    for ((i=1;i<=RECORDS;i++)); do
      SQL+="('$(rand_ip)','$(rand_user)','$(rand_mobile)')"
      ((i<RECORDS)) && SQL+=","
    done
    
    mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PWD" "$DB_NAME" <<<"
    CREATE TABLE IF NOT EXISTS $TB_NAME(
      id       INT AUTO_INCREMENT PRIMARY KEY,
      ip       VARCHAR(15) NOT NULL,
      username VARCHAR(50) NOT NULL,
      mobile   CHAR(11)    NOT NULL,
      KEY idx_mobile(mobile)
    );
    $SQL;
    "
    
    echo "OK. $RECORDS 新的数据添加到 $DB_NAME.$TB_NAME (starting from ID $((MAX_ID+1)))."
  1. 检查新的数据

    复制代码
    1 | 50.211.173.1    | Mona7447    | 18810022676 |
    | 1972 | 114.131.146.69  | Quinn8745   | 18310001620 |
    | 1973 | 187.141.110.177 | Sammy2000   | 15210020323 |
    | 1974 | 237.120.189.245 | Fred4123    | 13310001165 |
    | 1975 | 152.219.97.35   | Tina1293    | 17610012998 |
    | 1976 | 162.60.130.93   | Henry6128   | 17210023533 |
    | 1977 | 39.58.149.148   | Kate6250    | 15610014183 |
    | 1978 | 136.100.199.174 | Olga1198    | 15310027067 |
    | 1979 | 38.212.135.174  | Peter1276   | 15910025391 |
    | 1980 | 16.69.13.175    | Wendy7280   | 13510003224 |
    | 1981 | 80.84.213.199   | Gina2395    | 17710008313 |
    | 1982 | 125.69.66.27    | Jack5749    | 18410019520 |
    | 1983 | 26.78.245.53    | Tina3497    | 18910002653 |
    | 1984 | 149.236.231.49  | Carol1518   | 15010030166 |
    | 1985 | 228.32.242.161  | Carol5839   | 18510021882 |
    | 1986 | 37.251.12.255   | Zoe2381     | 15910003784 |
    | 1987 | 54.130.196.55   | Quinn6112   | 18710024819 |
    | 1988 | 165.26.157.46   | Uma2973     | 18710005858 |
    | 1989 | 116.15.159.140  | Leo4047     | 17710018837 |
    | 1990 | 186.60.139.253  | Gina9965    | 13010031614 |
    | 1991 | 32.116.12.63    | Tina4830    | 13910027045 |
    | 1992 | 192.21.80.180   | Wendy5562   | 17510024954 |
    | 1993 | 140.173.190.205 | Henry3787   | 13810007033 |
    | 1994 | 235.76.87.6     | Mona7221    | 18510024924 |
    | 1995 | 48.12.213.4     | Mona5646    | 17810027487 |
    | 1996 | 202.57.152.34   | Jack8709    | 13610001444 |
    | 1997 | 170.40.89.50    | Xavier2580  | 13510007627 |
    | 1998 | 207.247.89.180  | Carol4984   | 17510003099 |
    | 1999 | 11.74.42.191    | Leo3005     | 17010005401 |
    | 2000 | 77.214.127.12   | Quinn6290   | 13910028577 |
    +------+-----------------+-------------+-------------+
  1. 第一次增量备份(基于全量备份)

    复制代码
    xtrabackup --backup \
      --target-dir=/home/backup/inc01 \
      --incremental-basedir=/home/backup/full \
      --user=root \
      --password=123 \
      --host=127.0.0.1 \
      --port=3306
  2. 第二次增量备份(基于inc01)

    1. 执行脚本去再加入数据

      复制代码
      | 2976 | 11.189.78.19    | Iris2046    | 17310006847 |
      | 2977 | 43.45.39.70     | Mona8625    | 13210008013 |
      | 2978 | 218.198.189.169 | Henry3688   | 17110012440 |
      | 2979 | 171.69.14.86    | Tina9156    | 17410002798 |
      | 2980 | 44.249.121.140  | Wendy6370   | 18610017135 |
      | 2981 | 219.173.37.70   | Fred5309    | 15310000622 |
      | 2982 | 16.211.254.200  | Yolanda1638 | 18310017474 |
      | 2983 | 99.155.149.176  | Iris1431    | 15910015020 |
      | 2984 | 21.50.219.134   | Fred3068    | 13110020478 |
      | 2985 | 192.217.2.158   | Dave9980    | 15210008564 |
      | 2986 | 117.137.17.59   | Dave8888    | 15010024830 |
      | 2987 | 151.50.244.184  | Alice2742   | 17710013259 |
      | 2988 | 23.87.230.116   | Alice6977   | 13310029974 |
      | 2989 | 246.74.136.28   | Eva4844     | 17810013224 |
      | 2990 | 251.48.107.176  | Sammy6930   | 15610001694 |
      | 2991 | 161.241.175.52  | Uma7078     | 13610031252 |
      | 2992 | 47.186.191.13   | Uma7239     | 15210022271 |
      | 2993 | 95.142.141.154  | Olga5257    | 13610029869 |
      | 2994 | 8.103.209.200   | Victor9020  | 18010016082 |
      | 2995 | 182.234.232.220 | Leo6194     | 13510009070 |
      | 2996 | 86.251.175.245  | Mona7331    | 13110014020 |
      | 2997 | 182.41.194.168  | Alice7727   | 17810022203 |
      | 2998 | 221.63.142.142  | Victor7877  | 15710006483 |
      | 2999 | 184.37.170.148  | Peter6793   | 17010032764 |
      | 3000 | 23.197.68.206   | Bob9457     | 13510019290 |
      +------+-----------------+-------------+-------------+
    2. 增量备份()

      复制代码
      xtrabackup --backup \
        --target-dir=/home/backup/inc02 \
        --incremental-basedir=/home/backup/inc01 \
        --user=root \
        --password=123 \
        --host=127.0.0.1 \
        --port=3306
  1. 合并到全量备份数据

    复制代码
    # 1. 准备全量备份
    xtrabackup --prepare --apply-log-only --target-dir=/home/backup/full
    
    # 2. 合并第一次增量
    xtrabackup --prepare --target-dir=/home/backup/full \
              --incremental-dir=/home/backup/inc01
    
    # 3. 合并第二次增量(重新执行 1)
    xtrabackup --prepare --target-dir=/home/backup/full \
              --incremental-dir=/home/backup/inc02
    
    # 4. 将完整数控重新变成可恢复的备份
    xtrabackup --prepare --target-dir=/home/backup/full

3.4 恢复数据

  1. 删除库(测试环境)

    复制代码
    drop database test;
  1. 使用最新数据恢复

    复制代码
    # 停止数据库
    systemctl stop mysqld
    
    # 将数据变成可恢复的数据
    xtrabackup --prepare --target-dir=/home/backup/full
    
    # (删除)源Data
    mv /usr/local/mysql/data /usr/local/mysql/data.bak
    
    # copy-back(真实恢复数据)
    xtrabackup --copy-back --target-dir=/home/backup/full
    
    # 修权限
    chown -R mysql:mysql /usr/local/mysql/data
    
    # MySQL
    systemctl start mysqld
  1. 检查数据

    复制代码
    | 2983 | 99.155.149.176  | Iris1431    | 15910015020 |
    | 2984 | 21.50.219.134   | Fred3068    | 13110020478 |
    | 2985 | 192.217.2.158   | Dave9980    | 15210008564 |
    | 2986 | 117.137.17.59   | Dave8888    | 15010024830 |
    | 2987 | 151.50.244.184  | Alice2742   | 17710013259 |
    | 2988 | 23.87.230.116   | Alice6977   | 13310029974 |
    | 2989 | 246.74.136.28   | Eva4844     | 17810013224 |
    | 2990 | 251.48.107.176  | Sammy6930   | 15610001694 |
    | 2991 | 161.241.175.52  | Uma7078     | 13610031252 |
    | 2992 | 47.186.191.13   | Uma7239     | 15210022271 |
    | 2993 | 95.142.141.154  | Olga5257    | 13610029869 |
    | 2994 | 8.103.209.200   | Victor9020  | 18010016082 |
    | 2995 | 182.234.232.220 | Leo6194     | 13510009070 |
    | 2996 | 86.251.175.245  | Mona7331    | 13110014020 |
    | 2997 | 182.41.194.168  | Alice7727   | 17810022203 |
    | 2998 | 221.63.142.142  | Victor7877  | 15710006483 |
    | 2999 | 184.37.170.148  | Peter6793   | 17010032764 |
    | 3000 | 23.197.68.206   | Bob9457     | 13510019290 |
    +------+-----------------+-------------+-------------+

四、定时任务

当然,手动完全是不健康的,那么为什么不去做一个脚本,然后定时任务去定时执行脚本

4.1 完整脚本脚本

当然,你可以备份到另外一个主机上,也可以本机放一,另一个主机也放,双保证

vim back.sh

复制代码
   #!/bin/bash
   set -euo pipefail

   # 基本变量
   DB_IP="127.0.0.1"
   DB_PASSWORD="Backup@123"
   DB_USER="backup"
   DB_PORT="3306"

   # 全量备份目录
   FULL_DIR="/home/backup/full"

   # 增量备份目录(带时间戳)
   ICN_DIR="/home/backup/inc_$(date +%Y%m%d_%H%M%S)"

   # 临时归档目录
   TAR_DIR="/home/backup/tar"

   # 远程备份仓库
   REMOTE_IP="root@192.168.129.251"
   REMOTE_CONT="/var/DB1292_BACK/"
   REMOTE_FULL="FULL-$(date +%Y%m%d_%H%M%S).tar"

   # 创建目录
   mkdir -p "$ICN_DIR"
   mkdir -p "$TAR_DIR"

   echo "[$(date '+%Y-%m-%d %H:%M:%S')] 开始增量备份..."

   # 增量备份
   xtrabackup --backup \
     --target-dir="$ICN_DIR" \
     --incremental-basedir="$FULL_DIR" \
     --user="$DB_USER" \
     --password="$DB_PASSWORD" \
     --host="$DB_IP" \
     --port="$DB_PORT"

   echo "[$(date '+%Y-%m-%d %H:%M:%S')] 增量备份完成"

   # 合并到全量备份
   # 全量备份初步 prepare
   xtrabackup --prepare --apply-log-only --target-dir="$FULL_DIR"
   echo "[$(date '+%Y-%m-%d %H:%M:%S')] 全量备份初步 prepare 完成"

   # 应用增量备份
   xtrabackup --prepare \
     --target-dir="$FULL_DIR" \
     --incremental-dir="$ICN_DIR"
   echo "[$(date '+%Y-%m-%d %H:%M:%S')] 增量备份合并完成"

   # 最终 prepare 生成可恢复备份
   xtrabackup --prepare --target-dir="$FULL_DIR"
   echo "[$(date '+%Y-%m-%d %H:%M:%S')] 最终 prepare 完成,可恢复备份已生成"

   # 打包归档并发送
   tar -cf "$TAR_DIR/$REMOTE_FULL" -C "$FULL_DIR" .
   scp "$TAR_DIR/$REMOTE_FULL" "$REMOTE_IP:$REMOTE_CONT"

   echo -e "[$(date '+%Y-%m-%d %H:%M:%S')] 增量备份完成,已合并到全量备份并发送到远程服务器"
  1. 设置定时任务

    复制代码
    crontab -e
    
    # 每天晚上12点执行脚本,并把执行过程归档到日志中
    0 0 * * * /bin/bash /home/backup/backup_incremental.sh >> /home/backup/backup.log 2>&1
相关推荐
IvorySQL4 小时前
PostgreSQL 日报|修复截断 zstd 备份检测(10 月 9 日)
数据库·postgresql
刘胡子大叔4 小时前
SQL 脚本的导入顺序
数据库·sql
代码什么用4 小时前
Spring对IoC的实现
数据库·spring
hz567897 小时前
涉密视频会议设备配置指南:终端、音视频采集与配套设施选型
服务器·网络·数据库·安全·实时音视频·信息与通信·智能硬件
广州浮点FLOATLIC7 小时前
许可证服务器迁移后软件打不开:研发 IT 怎样定位连接问题
linux·服务器·数据库
程序员Sunday7 小时前
MySQL 为什么使用 B+ 树索引?把范围查询、回表和覆盖索引连起来
数据库·mysql
半杯咖啡半行码7 小时前
Qt开发实战:数据库、MV 模式、QProcess与串口通信全攻略
数据库·qt
Yyyyyy~7 小时前
[ Mysql ] 库的操作
mysql
小米里的大麦7 小时前
16 MySQL 事务
数据库·mysql
西柚小萌新7 小时前
【LLM&&AI应用开发 八股文】--4.3.Agent智能体(下)
java·开发语言·数据库