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
相关推荐
Turnip12022 天前
深度解析:为什么简单的数据库"写操作"会在 MySQL 中卡住?
后端·mysql
爱可生开源社区2 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1772 天前
《从零搭建NestJS项目》
数据库·typescript
加号32 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏2 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐2 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
百锦再2 天前
Django实现接口token检测的实现方案
数据库·python·django·sqlite·flask·fastapi·pip
WeiXin_DZbishe2 天前
基于django在线音乐数据采集的设计与实现-计算机毕设 附源码 22647
javascript·spring boot·mysql·django·node.js·php·html5
tryCbest2 天前
数据库SQL学习
数据库·sql
jnrjian2 天前
ORA-01017 查找机器名 用户名 以及library cache lock 参数含义
数据库·oracle