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
相关推荐
宸津-代码粉碎机2 小时前
用MySQL玩转数据可视化
数据库·mysql·信息可视化
步步为营DotNet2 小时前
深度探索.NET 中ILogger:构建稳健日志系统的核心组件
数据库·.net
砚边数影2 小时前
线性回归原理(二):梯度下降算法,Java实现单变量/多变量拟合
java·数据库·算法·线性回归·kingbase·kingbasees·金仓数据库
licheng99672 小时前
工具、测试与部署
jvm·数据库·python
红队it2 小时前
【数据分析+机器学习】基于机器学习的招聘数据分析可视化预测推荐系统(完整系统源码+数据库+开发笔记+详细部署教程)✅
数据库·机器学习·数据分析
明洞日记2 小时前
【软考每日一练020】深入解析事务(Transaction)与ACID特性的工程实现
数据库·oracle
洋不写bug3 小时前
数据库的约束和主键
数据库
你想考研啊3 小时前
sqlserver新建用户和表
数据库
李慕婉学姐3 小时前
【开题答辩过程】以《基于uniapp的养宠互助服务程序设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
android·mysql·uni-app