MySQL 全量 + 增量备份脚本(RPM 安装)实践与问题解析

前言

一、备份方案概述

二、最终备份脚本

三、遇到的问题与解决方案

[1. 增量备份只备份了 mysql-bin.index](#1. 增量备份只备份了 mysql-bin.index)

[2. 增量备份为空或不完整](#2. 增量备份为空或不完整)

[3. 新增 binlog 文件数量增加](#3. 新增 binlog 文件数量增加)

[4. crontab 日志记录](#4. crontab 日志记录)

四、总结

五、附录

rpm安装mysql步骤

1.下载RPM以及依赖包

2.下载MYSQL所需的依赖包

3.安装RPM包

4.启动mysql

5.修改初始密码

6.修改配置文件

7.修改密码

8.测试登录

六、脚本参数详解

脚本逐行解析

配置区

创建备份目录

全量备份(每周日执行)

增量备份(每天执行)

自动删除过期备份

脚本结束

前言

在实际生产环境中,数据库备份是保障数据安全的重要环节。本文总结了基于 RPM 安装的 MySQL 5.7 的全量 + 增量备份方案,结合遇到的问题和解决方法,为大家提供一个完整参考。


一、备份方案概述

  • 全量备份 :每周日使用 mysqldump 备份所有数据库到 SQL 文件

  • 增量备份 :每天基于 MySQL 二进制日志(binlog) 进行备份

  • 自动清理:保留最近 7 天的备份文件

  • 目录结构

复制代码
/var/lib/mysql/mysql_backup/
├── full/       # 全量备份目录
└── increment/  # 增量备份目录

二、最终备份脚本

复制代码
#!/bin/bash
# MySQL 全量+增量备份脚本
​
# 配置区
BACKUP_ROOT=/var/lib/mysql/mysql_backup
FULL_DIR=$BACKUP_ROOT/full
INCR_DIR=$BACKUP_ROOT/increment
MYSQL_USER=root
MYSQL_PASS='123456'
DATE=$(date +%F)
WEEKDAY=$(date +%u)
BINLOG_DIR=/var/lib/mysql
RETENTION_DAYS=7
​
# 创建备份目录
mkdir -p $FULL_DIR
mkdir -p $INCR_DIR
​
# 每周日执行全量备份
if [ "$WEEKDAY" -eq 7 ]; then
    echo "[`date`] 开始全量备份..."
    FULL_FILE=$FULL_DIR/all_$DATE.sql
    mysqldump -u$MYSQL_USER -p$MYSQL_PASS --all-databases --single-transaction --flush-logs > $FULL_FILE
    if [ $? -eq 0 ]; then
        echo "[`date`] 全量备份完成:$FULL_FILE"
    else
        echo "[`date`] 全量备份失败!"
    fi
fi
​
# 每日增量备份(基于 binlog)
echo "[`date`] 开始增量备份..."
mysql -u$MYSQL_USER -p$MYSQL_PASS -e "FLUSH LOGS;"
# 获取倒数第二个完整 binlog 文件
PREV_BINLOG=$(ls -tr $BINLOG_DIR/mysql-bin.[0-9]* | tail -2 | head -1)
​
if [ -f "$PREV_BINLOG" ]; then
    cp $PREV_BINLOG $INCR_DIR/$(basename $PREV_BINLOG).$DATE
    if [ $? -eq 0 ]; then
        echo "[`date`] 增量备份完成:$INCR_DIR/$(basename $PREV_BINLOG).$DATE"
    else
        echo "[`date`] 增量备份失败!"
    fi
else
    echo "[`date`] 没找到可用的 binlog 文件"
fi
​
# 自动删除 7 天前备份
echo "[`date`] 开始清理7天前的备份..."
find $FULL_DIR -type f -mtime +$RETENTION_DAYS -name "*.sql" -exec rm -f {} \;
find $INCR_DIR -type f -mtime +$RETENTION_DAYS -name "mysql-bin.*" -exec rm -f {} \;
echo "[`date`] 清理完成"
​
echo "[`date`] 备份任务完成"

测试截图


三、遇到的问题与解决方案

1. 增量备份只备份了 mysql-bin.index

现象 :执行脚本后,增量备份目录中出现了 mysql-bin.index.日期 文件,而不是实际的 binlog 文件(如 mysql-bin.000002)。

原因

  • 原脚本中使用了:
复制代码
PREV_BINLOG=$(ls -tr $BINLOG_DIR/mysql-bin.* | tail -2 | head -1)
  • mysql-bin.* 会匹配所有文件,包括 .index 文件

  • 如果目录中有 mysql-bin.index,shell 排序可能取到了索引文件,导致备份文件不包含实际事务数据

解决方案

复制代码
PREV_BINLOG=$(ls -tr $BINLOG_DIR/mysql-bin.[0-9]* | tail -2 | head -1)
  • 使用 mysql-bin.[0-9]* 只匹配数字序号文件

  • 排除索引文件,保证增量备份内容完整


2. 增量备份为空或不完整

现象:新生成的 binlog 文件可能正在写入,直接备份会导致空或未完成事务。

原因

  • 脚本使用 SHOW MASTER STATUS 获取当前 binlog 文件

  • 当前文件可能刚生成,还未写入任何事务

解决方案

  • 备份倒数第二个文件,而不是最新文件:
复制代码
PREV_BINLOG=$(ls -tr $BINLOG_DIR/mysql-bin.[0-9]* | tail -2 | head -1)
  • 最新文件仍在写入,倒数第二个文件已经完成,可以安全备份

3. 新增 binlog 文件数量增加

现象 :每次执行 FLUSH LOGS; 后,binlog 文件会生成新的序号,如 mysql-bin.000002

原因

  • MySQL FLUSH LOGS; 会滚动当前 binlog,生成新的文件

  • 是 MySQL 的标准行为,不是脚本错误

注意

  • 每次增量备份都应复制倒数第二个文件

  • 保证备份完整、不会备份正在写入的文件


4. crontab 日志记录

  • 脚本可以加入定时任务:
复制代码
0 1 * * * /bin/bash /var/lib/mysql/mysql_backup/mysql_backup.sh >> /var/log/mysql_backup.log 2>&1
  • 注意:/var/log/mysql_backup.log 路径不存在时,>> 会自动创建文件,但父目录必须存在

四、总结

  1. 全量备份 使用 mysqldump 每周一次

  2. 增量备份 基于 binlog,注意只备份已完成的 binlog 文件

  3. 清理机制保证备份目录不无限膨胀

  4. 脚本问题排查要点

  • 增量备份误备份索引文件 → 用数字匹配避免

  • 空增量备份 → 复制倒数第二个文件

  • binlog 文件不断增加 → FLUSH LOGS 导致,正常

日志管理

  • 全量备份使用 .sql 文件

  • 增量备份使用 mysql-bin 文件

  • 自动保留 7 天备份

脚本中常用参数

  • ls -tr:按时间排序文件

  • basename:去掉路径,只取文件名

  • [ -f "$file" ]:判断普通文件是否存在

  • $?:判断上一条命令是否成功

通过这套方案,可以在 MySQL RPM 安装环境下实现 安全、稳定、可自动化的全量 + 增量备份

五、附录

rpm安装mysql步骤

1.下载RPM以及依赖包

复制代码
# 下载 MySQL 5.7 的 YUM 仓库配置包
wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
# 安装 repo 配置包
sudo rpm -ivh mysql57-community-release-el7-11.noarch.rpm

2.下载MYSQL所需的依赖包

复制代码
cd /opt
mkdir mysql5720_rpms
#--resolve 自动下载依赖,--destdir 指定保存目录
yumdownloader --resolve --destdir=/opt/mysql5720_rpms mysql-community-server-5.7.20

3.安装RPM包

复制代码
cd /opt/mysql5720_rpms
yum localinstall -y *.rpm

4.启动mysql

复制代码
systemctl start mysqld

5.修改初始密码

复制代码
mysql -uroot -p$(grep "password" /var/log/mysqld.log | awk '{print $NF}') --connect-expired-password -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'Admin@123';"

6.修改配置文件

复制代码
vim /etc/my.cnf
[mysqld]
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
port = 3306
bind-address = 0.0.0.0
default-storage-engine=INNODB
character-set-server=utf8
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
validate_password_policy=LOW    # 降低强度策略(仅检查长度)
validate_password_length=6       # 最小密码长度设为6位
#log-bin=mysql-bin (可选:开启二进制日志)
#binlog_format=MIXED (可选:指定二进制日志的记录格式)
server-id=1
​
systemctl restart mysqld

7.修改密码

复制代码
mysql -uroot -pAdmin@123 -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '123456';"

8.测试登录

复制代码
mysql -uroot -p123456

六、脚本参数详解

脚本逐行解析

复制代码
#!/bin/bash
  • 指定脚本解释器为 bash,保证脚本在 Linux 系统下用 Bash 执行。

配置区

复制代码
BACKUP_ROOT=/var/lib/mysql/mysql_backup
  • 备份根目录,所有备份文件都存放在这里。
复制代码
FULL_DIR=$BACKUP_ROOT/full
INCR_DIR=$BACKUP_ROOT/increment
  • 全量备份目录和增量备份目录,便于分类管理备份。
复制代码
MYSQL_USER=root
MYSQL_PASS='123456'
  • MySQL 登录用户名和密码,用于执行 mysqldumpmysql 命令。

  • 注意 :命令行中使用密码会有安全提示,可使用 .my.cnf 文件避免明文密码。

复制代码
DATE=$(date +%F)
  • 获取当前日期,格式为 YYYY-MM-DD,用于给备份文件命名。

  • 示例:2025-10-01

复制代码
WEEKDAY=$(date +%u)
  • 获取当前星期几,1 = 星期一,7 = 星期日。用于判断是否执行全量备份。
复制代码
BINLOG_DIR=/var/lib/mysql
  • MySQL 二进制日志目录(RPM 安装默认 /var/lib/mysql),用于增量备份。
复制代码
RETENTION_DAYS=7
  • 自动清理多少天前的备份文件,这里设置为 7 天。

创建备份目录

复制代码
mkdir -p $FULL_DIR
mkdir -p $INCR_DIR
  • -p 参数表示递归创建目录,如果目录已存在不会报错。

  • 保证备份目录存在,避免 cpmysqldump 写入失败。


全量备份(每周日执行)

复制代码
if [ "$WEEKDAY" -eq 7 ]; then
    echo "[`date`] 开始全量备份..."
    FULL_FILE=$FULL_DIR/all_$DATE.sql
  • 判断今天是否是星期日,如果是则执行全量备份。

  • 全量备份文件命名为 all_YYYY-MM-DD.sql

复制代码
mysqldump -u$MYSQL_USER -p$MYSQL_PASS --all-databases --single-transaction --flush-logs > $FULL_FILE
  • mysqldump:MySQL 官方备份工具。

  • 参数解释:

    • -u$MYSQL_USER:登录用户名。

    • -p$MYSQL_PASS:登录密码。

    • --all-databases:备份所有数据库。

    • --single-transaction:对 InnoDB 表启用一致性快照,避免锁表。

    • --flush-logs:备份时刷新日志,生成新的二进制日志文件,便于增量备份。

  • > $FULL_FILE:将输出保存到全量备份文件。

复制代码
if [ $? -eq 0 ]; then
    echo "[`date`] 全量备份完成:$FULL_FILE"
else
    echo "[`date`] 全量备份失败!"
fi
  • $? 表示上一条命令执行状态码:

    • 0 表示成功

    • 非 0 表示失败

  • 根据状态输出备份结果。


增量备份(每天执行)

复制代码
echo "[`date`] 开始增量备份..."
mysql -u$MYSQL_USER -p$MYSQL_PASS -e "FLUSH LOGS;"
  • 每次增量备份前执行 FLUSH LOGS;

    • MySQL 生成一个新的二进制日志文件(如 mysql-bin.000003)。

    • 保证增量备份文件完整。

复制代码
PREV_BINLOG=$(ls -tr $BINLOG_DIR/mysql-bin.[0-9]* | tail -2 | head -1)
  • 获取最新两个 binlog 文件中倒数第二个(完整的上一个 binlog)。

  • 参数解释:

    • ls -tr

      • -t:按修改时间排序(最新的在前)

      • -r:反转顺序(最旧在前)

    • $BINLOG_DIR/mysql-bin.[0-9]*:匹配所有数字编号的 binlog 文件。

    • tail -2 | head -1:取倒数第二个文件(上一次的 binlog,用于增量备份)。

复制代码
if [ -f "$PREV_BINLOG" ]; then
    cp $PREV_BINLOG $INCR_DIR/$(basename $PREV_BINLOG).$DATE
  • -f:判断文件是否存在且为普通文件。

  • basename $PREV_BINLOG:获取文件名(去掉路径),避免复制时路径问题。

  • cp ... $INCR_DIR/....$DATE:复制 binlog 到增量目录,并加日期后缀。

复制代码
if [ $? -eq 0 ]; then
    echo "[`date`] 增量备份完成:$INCR_DIR/$(basename $PREV_BINLOG).$DATE"
else
    echo "[`date`] 增量备份失败!"
fi
  • 判断复制是否成功,输出结果。
复制代码
else
    echo "[`date`] 没找到可用的 binlog 文件"
fi
  • 如果 $PREV_BINLOG 不存在,则输出警告。

自动删除过期备份

复制代码
echo "[`date`] 开始清理7天前的备份..."
find $FULL_DIR -type f -mtime +$RETENTION_DAYS -name "*.sql" -exec rm -f {} \;
find $INCR_DIR -type f -mtime +$RETENTION_DAYS -name "mysql-bin.*" -exec rm -f {} \;
  • find:查找符合条件的文件并删除。

  • 参数解释:

    • $FULL_DIR / $INCR_DIR:查找路径。

    • -type f:只查找普通文件。

    • -mtime +$RETENTION_DAYS:修改时间超过 $RETENTION_DAYS 天。

    • -name "*.sql" / "mysql-bin.*":匹配文件名。

    • -exec rm -f {} \;:删除匹配文件。

复制代码
echo "[`date`] 清理完成"
  • 输出清理完成信息。

脚本结束

复制代码
echo "[`date`] 备份任务完成"
  • 输出最终备份完成的提示。
相关推荐
碰大点19 小时前
Ubuntu 16.04交叉编译arm-linux-gnueabihf的QT5.6.2
linux·arm开发·qt·ubuntu·arm-linux
小-黯19 小时前
Linux硬盘挂载脚本
linux·运维·服务器
PeaceKeeper719 小时前
简易的arm-linux库文件移植
linux·运维·arm开发
运维帮手大橙子19 小时前
最近面试题总结
linux·服务器·网络
zz-zjx20 小时前
MySQL 开源主从复制实战指南(SRE 可靠性优先版)
数据库·mysql·开源
计算机学姐1 天前
基于微信小程序的高校班务管理系统【2026最新】
java·vue.js·spring boot·mysql·微信小程序·小程序·mybatis
黄毛火烧雪下1 天前
【Ruby 】脚本和自动化语言 常用的内容
运维·自动化·ruby
Madison-No71 天前
【Linux】gcc/g++编辑器 && 初识动静态库 && 程序翻译过程
linux·服务器
小白不想白a1 天前
【shell】每日shell练习:安全日志入侵检测/系统配置文件合规检查
运维·服务器
字节逆旅1 天前
一个从从容容,一个连滚带爬:scp 与 rsync 的不同人生
linux