☰
MySQL 数据库全量 + 增量备份-Shell 脚本 + Percona XtraBackup ---实战手册
2026/10/29 2:10:55 网站建设 项目流程

实验名称:Shell 脚本实现 MySQL 企业级备份(每周全量、每日增量) 适用:Linux 运维、数据库运维实训 实验环境:CentOS7 / Rocky8、MySQL5.7 或 MySQL8.0、Percona XtraBackup 实验目标:

1. 理解数据库全量备份、增量备份原理与适用场景

2. 掌握 xtrabackup 热备工具使用(无锁 InnoDB 备份)

3. 编写 Shell 脚本自动实现:每周一次全量备份,每日增量备份

4. 掌握备份恢复完整流程,理解增量备份合并规则

5. 配置 crontab 定时任务,实现自动化备份

说明:本实验采用 Percona XtraBackup(物理热备),生产和教学最常用;mysqldump 逻辑备份无法原生增量,本实验不采用。

一、实验原理

1. 全量备份(完备)

复制 InnoDB 所有数据页,生成一份完整数据库副本。本实验设定周日执行全量备份,作为本周所有增量备份的基准备份。

2. 增量备份(增备)

对比基准全量备份,只备份自上次备份之后发生变化的数据页;周一至周六每日增量,依赖本周日的全量基备。

3. XtraBackup 核心特点

支持热备份,InnoDB 引擎不锁表;备份时记录 LSN(日志序列号),增量依靠 LSN 识别变更数据。

4. 恢复逻辑

先对基备做 prepare,按时间顺序依次合并所有增量备份,最后 apply-log 完成回滚,再拷贝回数据目录。

二、实验环境准备

2.1 环境信息

项目

参数

操作系统

CentOS7 / Rocky Linux 8

数据库

MySQL 5.7 / MySQL8.0

备份工具

percona-xtrabackup(2.4 版本适配 5.7,8.0 版本适配 MySQL8.0)

备份路径

/data/mysql_backup

定时策略

每日凌晨 02:00 执行;周日 = 全量,周一~周六 = 增量

2.2 安装依赖工具

# CentOS7 安装xtrabackup2.4 yum install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm percona-release enable-only tools release yum install -y percona-xtrabackup-24 # Rocky8 / MySQL8.0 dnf install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm percona-release enable-only tools release dnf install -y percona-xtrabackup-80

⚠️ 再次提醒:xtrabackup 是热备,MySQL 必须启动,不能 stop!

systemctl start mysqld
①先装依赖(EPEL 源,必须)
yum install -y epel-release yum install -y perl-DBD-MySQL perl-Digest-MD5 libaio
②下载 CentOS7 对应的 xtrabackup2.4 rpm 包
wget https://downloads.percona.com/downloads/Percona-XtraBackup-2.4/Percona-XtraBackup-2.4.28/binary/redhat/7/x86_64/percona-xtrabackup-24-2.4.28-1.el7.x86_64.rpm

③本地安装(自动解决依赖)
yum localinstall -y percona-xtrabackup-24-2.4.28-1.el7.x86_64.rpm

④验证
innobackupex --version

输出版本号就成功!

⑤验证备份命令(单独测试)
innobackupex --user=bkuser --password=Backup@2026 /data/mysql_backup/full/

2.3 MySQL 备份账号授权

登录 MySQL 执行:

mysql -u root -p[密码]

CREATE USER 'bkuser'@'localhost' IDENTIFIED BY 'Backup@2026'; GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT, PROCESS ON *.* TO 'bkuser'@'localhost'; FLUSH PRIVILEGES;

权限说明:

  • RELOAD:刷新表
  • LOCK TABLES:MyISAM 锁表备份
  • REPLICATION CLIENT:获取 binlog 位置
  • PROCESS:查看数据库进程

2.4 前置检查项

  1. MySQL 服务正常运行
  2. 磁盘空间充足,备份目录独立,不和数据库数据盘争抢 IO
  3. 关闭 SELinux(教学环境可选)
setenforce 0

三、Shell 备份脚本(mysql_backup.sh)

#!/bin/bash #==================================================== # 实验脚本:MySQL XtraBackup 全量+增量自动备份【最终修复版】 # 策略:周日全量备份,周一~周六增量备份 # 日志:/data/mysql_backup/backup.log # 修复:优先使用外部传入WEEK_DAY,外部不传才自动取date #==================================================== # ----------------------配置区---------------------- MYSQL_USER="bkuser" MYSQL_PASS="Backup@2026" # MYSQL_HOST="127.0.0.1" # MYSQL_PORT="3306" BACKUP_BASE="/data/mysql_backup" LOG_FILE="${BACKUP_BASE}/backup.log" RETENTION_DAY=14 # 备份保留14天,自动清理过期 DATE=$(date +%Y%m%d_%H%M%S) FULL_DIR="${BACKUP_BASE}/full" INCR_DIR="${BACKUP_BASE}/incr" # -------------------------------------------------- # 日志输出函数 log(){ echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a ${LOG_FILE} } # 创建目录 init_dir(){ mkdir -p ${BACKUP_BASE} ${FULL_DIR} ${INCR_DIR} } # 清理过期备份 clean_backup(){ log "=== 清理${RETENTION_DAY}天前的备份文件 ===" find ${BACKUP_BASE} -type d -mtime +${RETENTION_DAY} -exec rm -rf {} \; } # 查询最新全量备份(【仅增量备份才调用这个函数!】) get_base_full(){ BASE_FULL=$(ls -td ${FULL_DIR}/*/ 2>/dev/null | head -1) if [ -z "${BASE_FULL}" ];then log "【错误】未找到基准全量备份,请先手动执行一次全量备份!" exit 1 fi } # 全量备份函数 full_backup(){ log "==== 开始执行【全量备份】 ====" FULL_PATH="${FULL_DIR}/full_${DATE}" innobackupex --user=${MYSQL_USER} --password=${MYSQL_PASS} \ --no-timestamp ${FULL_PATH} >>${LOG_FILE} 2>&1 if [ $? -eq 0 ];then log "✅ 全量备份成功,路径:${FULL_PATH}" else log "❌ 全量备份执行失败!" exit 1 fi } # 增量备份函数 incr_backup(){ get_base_full # 只有增量才去找基备! log "==== 开始执行【增量备份】,基准备份:${BASE_FULL} ====" INCR_PATH="${INCR_DIR}/incr_${DATE}" innobackupex --user=${MYSQL_USER} --password=${MYSQL_PASS} \ --incremental ${INCR_PATH} \ --incremental-basedir=${BASE_FULL} \ --no-timestamp >>${LOG_FILE} 2>&1 if [ $? -eq 0 ];then log "✅ 增量备份成功,路径:${INCR_PATH}" else log "❌ 增量备份执行失败!" exit 1 fi } # =====================主流程【重点修复!】===================== init_dir clean_backup # 核心修复:如果外部没有传入WEEK_DAY,才自动获取星期 if [ -z "${WEEK_DAY}" ];then WEEK_DAY=$(date +%w) fi if [ ${WEEK_DAY} -eq 0 ];then # 周日:直接全量,不调用get_base_full full_backup else # 工作日:增量,内部调用get_base_full校验基备 incr_backup fi log "==== 本次备份任务执行结束 ====" exit 0

四、脚本部署与定时配置(实验步骤)

步骤 1:创建脚本文件

vim /data/mysql_backup/mysql_backup.sh

粘贴脚本内容,保存退出。

步骤 2:添加执行权限

chmod +x /data/mysql_backup/mysql_backup.sh

步骤 3:手动测试脚本(先测试周日全量,再测试增量)

# 手动强制执行全量(模拟周日) WEEK_DAY=0 /data/mysql_backup/mysql_backup.sh # 手动强制执行增量(模拟工作日) WEEK_DAY=1 /data/mysql_backup/mysql_backup.sh

查看日志校验:tail -f /data/mysql_backup/backup.log

步骤 4:配置 crontab 定时任务

crontab -e

写入定时规则:每日凌晨 2 点自动执行备份

0 2 * * * /data/mysql_backup/mysql_backup.sh

规则解释:0 分 2 时 每天 每月 星期任意 系统自动判断星期:周日触发全量,其余日期增量

查看定时任务:

crontab -l

五、备份恢复实验步骤【重点】

实验场景:周日全量备份 full_xxx,后续生成 incr1、incr2 增量备份;数据库误删,需要恢复到 incr2 时间点。 ⚠️ 恢复前提:停止 MySQL 服务,清空原有数据目录!

1. 停止 MySQL

systemctl stop mysqld

2. 准备基准全量备份(加 --redo-only,用于合并增量)

innobackupex --apply-log --redo-only /data/mysql_backup/full/full_20261025_020000

3. 按时间先后顺序合并增量备份(顺序不能乱!)

# 合并第一个增量 innobackupex --apply-log --redo-only /data/mysql_backup/full/full_20261025_020000 \ --incremental-dir=/data/mysql_backup/incr/incr_20261026_020000 # 合并第二个增量(最后一次合并去掉 --redo-only) innobackupex --apply-log /data/mysql_backup/full/full_20261025_020000 \ --incremental-dir=/data/mysql_backup/incr/incr_20261027_020000

4. 将合并完成的备份拷贝回 MySQL 数据目录

innobackupex --copy-back /data/mysql_backup/full/full_20261025_020000

5. 修改数据目录属主权限

chown -R mysql:mysql /var/lib/mysql

6. 启动 MySQL,验证数据

systemctl start mysqld

六、实验结果验证

1. 备份目录结构验证

/data/mysql_backup/ ├── full/ # 存放每周全量备份 ├── incr/ # 存放每日增量备份 └── backup.log # 备份日志

2. 备份成功标志:备份目录内存在xtrabackup_checkpoints文件

cat /data/mysql_backup/full/full_xxxx/xtrabackup_checkpoints
  • full-backup-type = full:全量
  • full-backup-type = incremental:增量

3. 日志查看:tail -20 /data/mysql_backup/backup.log

4. 恢复验证:登录 MySQL 核对表、数据是否还原成功

七、实验思考题(课后作业)

1. 为什么增量备份必须依赖本周的全量基备?如果基备损坏,增量备份还能用吗?

XtraBackup 增量备份只备份上一次备份(全量 / 增量)之后变化的数据页,它记录的是 LSN 增量,没有完整数据,必须以全量备份作为基础基线,一层层叠加增量数据。
✅ 基备损坏:对应的所有增量备份全部失效,无法恢复。

2. 恢复合并增量时,为什么最后一步不能加--redo-only?

--redo-only的作用:只应用 redo 日志,不回滚未提交事务,专门用于合并中间增量包(还会继续合并下一个增量)。 最后一个增量合并完成后,不再有后续增量,必须关闭--redo-only,让 xtrabackup 执行回滚未提交事务,生成一个一致性、可直接启动的实例;如果最后一步加了这个参数,数据库启动失败。

口诀:中间合并加 --redo-only,最后一次不加。

3. xtrabackup 和 mysqldump 备份有什么区别?各自适合什么场景?

对比

xtrabackup(物理热备)

mysqldump(逻辑备份)

备份形式

复制数据文件、ibd 物理页

导出 SQL 语句

锁

InnoDB 无锁热备;MyISAM 会 FTWRL

默认加全局读锁(5.7),单事务模式 InnoDB 可避免锁

速度

大数据量快

大库很慢

恢复

直接拷贝文件,恢复快

导入 SQL,恢复慢

跨版本

同版本最佳,跨版本兼容性差

兼容性好,跨版本迁移友好

适合场景

几十 G、上百 G 生产 InnoDB 大库,日常定时备份

小库、结构迁移、版本升级、导出单库单表、审计

4. 本脚本存在哪些不足?(提示:缺少异地备份、告警、备份校验)

1. 无备份有效性校验:备份完成后没有校验备份包是否损坏、没有做预恢复测试,备份成功不代表可用;

2. 无异地备份:只在本地磁盘存放备份,磁盘故障、服务器宕机则备份全部丢失;

3. 无告警机制:备份失败、磁盘满、超时没有短信 / 邮件 / 钉钉告警,故障无法及时感知;

4. 其他常见补充(面试加分):缺少磁盘空间预判、备份自动清理过期备份、备份加密、日志记录、备份超时控制。

5. 如果需要同时备份 MyISAM 引擎表,备份过程会发生什么?

MyISAM 不支持事务、没有 redo 日志。xtrabackup 备份到 MyISAM 表时,会触发FTWRL(FLUSH TABLES WITH READ LOCK),锁住所有 MyISAM 表,阻塞写入;直到 MyISAM 表文件拷贝完成之后才释放锁;InnoDB 部分依旧热备无锁。

风险:大 MyISAM 表会导致长时间锁表,业务写阻塞。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询