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
相关推荐
2601_949593657 小时前
深入解析CANN-acl应用层接口:构建高效的AI应用开发框架
数据库·人工智能
javachen__7 小时前
mysql新老项目版本选择
数据库·mysql
Dxy12393102167 小时前
MySQL如何高效查询表数据量:从基础到进阶的优化指南
数据库·mysql
Dying.Light7 小时前
MySQL相关问题
数据库·mysql
蜡笔小炘8 小时前
LVS -- 利用防火墙标签(FireWall Mark)解决轮询错误
服务器·数据库·lvs
韩立学长8 小时前
基于Springboot泉州旅游攻略平台d5h5zz02(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·旅游
Re.不晚8 小时前
MySQL进阶之战——索引、事务与锁、高可用架构的三重奏
数据库·mysql·架构
老邓计算机毕设8 小时前
SSM智慧社区信息化服务平台4v5hv(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·ssm 框架·智慧社区、·信息化平台
麦聪聊数据9 小时前
为何通用堡垒机无法在数据库运维中实现精准风控?
数据库·sql·安全·低代码·架构
2301_790300969 小时前
Python数据库操作:SQLAlchemy ORM指南
jvm·数据库·python