MySQL教程 / 第 160 节

第16章:备份策略与实践

数据备份是DBA最重要的工作之一,没有备份就没有安全感

16.1 备份的重要性 ⭐⭐⭐⭐⭐

16.1.1 为什么需要备份?

常见的数据丢失场景:

  • ❌ 硬件故障(磁盘损坏、服务器宕机)
  • ❌ 人为误操作(误删数据、DROP TABLE)
  • ❌ 软件Bug(应用程序错误)
  • ❌ 恶意攻击(SQL注入、勒索病毒)
  • ❌ 自然灾害(火灾、地震、水灾)

备份的作用:

  • ✅ 数据恢复(最重要)
  • ✅ 数据迁移
  • ✅ 搭建从库
  • ✅ 数据分析
  • ✅ 合规要求

血泪教训:

没有备份 = 没有工作
没有测试的备份 = 没有备份

16.2 备份类型

16.2.1 逻辑备份 vs 物理备份

对比项逻辑备份物理备份
备份内容SQL语句数据文件
备份工具mysqldump、mysqlpumpXtraBackup、LVM快照
备份速度
恢复速度
跨平台✅ 支持❌ 不支持
跨版本✅ 支持⚠️ 有限制
占用空间小(可压缩)
适用场景小数据库、跨平台大数据库、快速恢复

16.2.2 全量备份 vs 增量备份

全量备份(Full Backup):

  • 备份所有数据
  • 恢复简单
  • 占用空间大
  • 备份时间长

增量备份(Incremental Backup):

  • 只备份变化的数据
  • 节省空间
  • 恢复复杂(需要全量+所有增量)
  • 备份时间短

差异备份(Differential Backup):

  • 备份自上次全量备份后的所有变化
  • 介于全量和增量之间
  • 恢复需要全量+最后一次差异

16.2.3 热备份 vs 冷备份

热备份(Hot Backup):

  • 数据库在线备份
  • 不影响业务
  • 推荐使用

温备份(Warm Backup):

  • 备份时只能读,不能写
  • 影响部分业务

冷备份(Cold Backup):

  • 停止数据库备份
  • 影响业务
  • 不推荐

16.3 mysqldump逻辑备份 ⭐⭐⭐⭐⭐

16.3.1 mysqldump基本用法

# 备份单个数据库
mysqldump -u root -p database_name > backup.sql

# 备份多个数据库
mysqldump -u root -p --databases db1 db2 db3 > backup.sql

# 备份所有数据库
mysqldump -u root -p --all-databases > all_backup.sql

# 备份单个表
mysqldump -u root -p database_name table_name > table_backup.sql

# 备份多个表
mysqldump -u root -p database_name table1 table2 > tables_backup.sql

16.3.2 mysqldump重要参数

# 完整的备份命令(推荐)
mysqldump -u root -p \
  --single-transaction \      # InnoDB一致性备份(不锁表)
  --master-data=2 \           # 记录binlog位置(注释形式)
  --flush-logs \              # 刷新binlog
  --routines \                # 备份存储过程和函数
  --triggers \                # 备份触发器
  --events \                  # 备份事件
  --hex-blob \                # 二进制数据使用十六进制
  --default-character-set=utf8mb4 \  # 字符集
  database_name > backup.sql

# 参数说明:
# --single-transaction:
#   - 适用于InnoDB
#   - 保证备份的一致性
#   - 不锁表,不影响业务
#   - ⭐ 强烈推荐

# --master-data=2:
#   - 记录备份时的binlog位置
#   - =1:直接写入CHANGE MASTER语句
#   - =2:以注释形式写入(推荐)
#   - 用于搭建主从复制

# --flush-logs:
#   - 备份前刷新binlog
#   - 生成新的binlog文件
#   - 便于增量备份

# --lock-all-tables:
#   - 锁定所有表(MyISAM需要)
#   - 会影响业务
#   - InnoDB不需要

# --quick:
#   - 快速备份
#   - 不缓冲查询结果
#   - 大表必须使用

# --compress:
#   - 压缩传输数据
#   - 减少网络传输

16.3.3 mysqldump备份示例

# 示例1:备份单个数据库(InnoDB)
mysqldump -u root -p \
  --single-transaction \
  --master-data=2 \
  --flush-logs \
  --routines \
  --triggers \
  mydb > mydb_backup_$(date +%Y%m%d).sql

# 示例2:备份所有数据库
mysqldump -u root -p \
  --all-databases \
  --single-transaction \
  --master-data=2 \
  --flush-logs \
  --routines \
  --triggers \
  --events > all_backup_$(date +%Y%m%d).sql

# 示例3:只备份表结构
mysqldump -u root -p \
  --no-data \
  database_name > schema_only.sql

# 示例4:只备份数据
mysqldump -u root -p \
  --no-create-info \
  database_name > data_only.sql

# 示例5:备份并压缩
mysqldump -u root -p \
  --single-transaction \
  database_name | gzip > backup.sql.gz

# 示例6:远程备份
mysqldump -h remote_host -u root -p \
  --single-transaction \
  database_name > remote_backup.sql

16.3.4 mysqldump恢复

# 恢复数据库
mysql -u root -p database_name < backup.sql

# 恢复所有数据库
mysql -u root -p < all_backup.sql

# 恢复压缩的备份
gunzip < backup.sql.gz | mysql -u root -p database_name

# 恢复时显示进度
pv backup.sql | mysql -u root -p database_name

# 恢复前创建数据库
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS mydb"
mysql -u root -p mydb < backup.sql

16.3.5 mysqldump的优缺点

优点:

  • ✅ 简单易用
  • ✅ 跨平台、跨版本
  • ✅ 可以查看和编辑备份文件
  • ✅ 可以选择性恢复
  • ✅ 适合小数据库

缺点:

  • ❌ 备份速度慢
  • ❌ 恢复速度慢
  • ❌ 占用CPU和内存
  • ❌ 不适合大数据库(>100GB)

16.4 mysqlpump逻辑备份

16.4.1 mysqlpump概述

# mysqlpump是MySQL 5.7新增的备份工具
# 相比mysqldump的改进:
# ✅ 支持并行备份(多线程)
# ✅ 备份速度更快
# ✅ 支持备份用户
# ✅ 支持压缩

# 基本用法
mysqlpump -u root -p database_name > backup.sql

# 并行备份(4个线程)
mysqlpump -u root -p \
  --default-parallelism=4 \
  database_name > backup.sql

# 压缩备份
mysqlpump -u root -p \
  --compress-output=LZ4 \
  database_name > backup.sql.lz4

16.4.2 mysqlpump vs mysqldump

特性mysqldumpmysqlpump
并行备份
备份速度
压缩需要外部工具✅ 内置
备份用户
成熟度一般
推荐度⭐⭐⭐⭐⭐⭐⭐⭐

16.5 XtraBackup物理备份 ⭐⭐⭐⭐⭐

16.5.1 XtraBackup概述

XtraBackup特点:

  • ✅ Percona开发的开源工具
  • ✅ 物理备份(直接复制数据文件)
  • ✅ 热备份(不锁表)
  • ✅ 支持增量备份
  • ✅ 备份速度快
  • ✅ 恢复速度快
  • ✅ 适合大数据库

版本选择:

  • MySQL 5.7 → XtraBackup 2.4
  • MySQL 8.0 → XtraBackup 8.0

16.5.2 XtraBackup安装

# CentOS/RHEL安装
yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpm
yum install percona-xtrabackup-24

# Ubuntu/Debian安装
wget https://repo.percona.com/apt/percona-release_latest.generic_all.deb
dpkg -i percona-release_latest.generic_all.deb
apt-get update
apt-get install percona-xtrabackup-24

# 验证安装
xtrabackup --version

16.5.3 XtraBackup全量备份

# 全量备份
xtrabackup --backup \
  --user=root \
  --password=your_password \
  --target-dir=/backup/full_backup

# 参数说明:
# --backup:执行备份
# --target-dir:备份目录
# --user:MySQL用户
# --password:MySQL密码

# 备份完成后的目录结构:
/backup/full_backup/
├── ibdata1              # 系统表空间
├── mysql/               # mysql系统库
├── mydb/                # 业务数据库
│   ├── table1.ibd
│   └── table2.ibd
├── xtrabackup_checkpoints  # 检查点信息
├── xtrabackup_info         # 备份信息
└── xtrabackup_logfile      # 事务日志

16.5.4 XtraBackup增量备份

# 第一次全量备份
xtrabackup --backup \
  --user=root \
  --password=your_password \
  --target-dir=/backup/full

# 第一次增量备份(基于全量)
xtrabackup --backup \
  --user=root \
  --password=your_password \
  --target-dir=/backup/inc1 \
  --incremental-basedir=/backup/full

# 第二次增量备份(基于第一次增量)
xtrabackup --backup \
  --user=root \
  --password=your_password \
  --target-dir=/backup/inc2 \
  --incremental-basedir=/backup/inc1

# 增量备份原理:
# 只备份自上次备份后修改的数据页
# 通过LSN(Log Sequence Number)判断

16.5.5 XtraBackup恢复

# 恢复全量备份

# 1. 准备备份(应用事务日志)
xtrabackup --prepare \
  --target-dir=/backup/full

# 2. 停止MySQL
systemctl stop mysqld

# 3. 清空数据目录
rm -rf /var/lib/mysql/*

# 4. 恢复数据
xtrabackup --copy-back \
  --target-dir=/backup/full

# 5. 修改权限
chown -R mysql:mysql /var/lib/mysql

# 6. 启动MySQL
systemctl start mysqld

# 恢复增量备份

# 1. 准备全量备份(不回滚未提交的事务)
xtrabackup --prepare --apply-log-only \
  --target-dir=/backup/full

# 2. 应用第一次增量
xtrabackup --prepare --apply-log-only \
  --target-dir=/backup/full \
  --incremental-dir=/backup/inc1

# 3. 应用第二次增量(最后一次不加--apply-log-only)
xtrabackup --prepare \
  --target-dir=/backup/full \
  --incremental-dir=/backup/inc2

# 4. 恢复数据(同全量恢复)
xtrabackup --copy-back \
  --target-dir=/backup/full

16.5.6 XtraBackup压缩备份

# 压缩备份
xtrabackup --backup \
  --user=root \
  --password=your_password \
  --compress \
  --compress-threads=4 \
  --target-dir=/backup/compressed

# 解压备份
xtrabackup --decompress \
  --target-dir=/backup/compressed

# 删除压缩文件
find /backup/compressed -name "*.qp" -delete

# 准备和恢复(同普通备份)
xtrabackup --prepare --target-dir=/backup/compressed
xtrabackup --copy-back --target-dir=/backup/compressed

16.6 备份策略设计 ⭐⭐⭐⭐⭐

16.6.1 备份策略原则

3-2-1原则:

  • 3份数据:至少保留3份数据副本
  • 2种介质:使用2种不同的存储介质
  • 1份异地:至少1份存储在异地

备份频率:

  • 全量备份:每周1次
  • 增量备份:每天1次
  • binlog备份:实时或每小时

保留策略:

  • 每日备份:保留7天
  • 每周备份:保留4周
  • 每月备份:保留12个月
  • 年度备份:永久保留

16.6.2 小型数据库备份策略(<10GB)

# 策略:每天全量备份

# 备份脚本:/backup/scripts/daily_backup.sh
#!/bin/bash

BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d)
MYSQL_USER="root"
MYSQL_PASSWORD="your_password"

# 创建备份目录
mkdir -p $BACKUP_DIR/$DATE

# 全量备份
mysqldump -u$MYSQL_USER -p$MYSQL_PASSWORD \
  --all-databases \
  --single-transaction \
  --master-data=2 \
  --flush-logs \
  --routines \
  --triggers \
  --events | gzip > $BACKUP_DIR/$DATE/all_databases.sql.gz

# 删除7天前的备份
find $BACKUP_DIR -type d -mtime +7 -exec rm -rf {} \;

# 定时任务:每天凌晨2点执行
# crontab -e
# 0 2 * * * /backup/scripts/daily_backup.sh

16.6.3 中型数据库备份策略(10GB-100GB)

# 策略:每周全量 + 每天增量

# 全量备份脚本:/backup/scripts/weekly_full.sh
#!/bin/bash

BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d)

# 全量备份
xtrabackup --backup \
  --user=root \
  --password=your_password \
  --target-dir=$BACKUP_DIR/full_$DATE

# 定时任务:每周日凌晨2点执行
# 0 2 * * 0 /backup/scripts/weekly_full.sh

# 增量备份脚本:/backup/scripts/daily_inc.sh
#!/bin/bash

BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d)

# 查找最新的备份(全量或增量)
LATEST_BACKUP=$(ls -td $BACKUP_DIR/* | head -1)

# 增量备份
xtrabackup --backup \
  --user=root \
  --password=your_password \
  --target-dir=$BACKUP_DIR/inc_$DATE \
  --incremental-basedir=$LATEST_BACKUP

# 定时任务:每天凌晨3点执行(周日除外)
# 0 3 * * 1-6 /backup/scripts/daily_inc.sh

16.6.4 大型数据库备份策略(>100GB)

# 策略:XtraBackup + binlog备份

# 全量备份:每周1次
# 增量备份:每天1次
# binlog备份:每小时1次

# binlog备份脚本:/backup/scripts/binlog_backup.sh
#!/bin/bash

BACKUP_DIR="/backup/binlog"
DATE=$(date +%Y%m%d_%H%M)
MYSQL_DATADIR="/var/lib/mysql"

# 创建备份目录
mkdir -p $BACKUP_DIR/$DATE

# 刷新binlog
mysql -u root -p -e "FLUSH LOGS"

# 复制binlog(除了最新的)
cd $MYSQL_DATADIR
for file in $(ls mysql-bin.* | head -n -1); do
    cp $file $BACKUP_DIR/$DATE/
done

# 定时任务:每小时执行
# 0 * * * * /backup/scripts/binlog_backup.sh

16.7 备份验证与测试 ⭐⭐⭐⭐⭐

16.7.1 为什么要验证备份?

没有测试的备份 = 没有备份

验证内容:

  • ✅ 备份文件完整性
  • ✅ 备份可以成功恢复
  • ✅ 恢复后数据正确性
  • ✅ 恢复时间是否满足RTO

16.7.2 备份验证脚本

# 验证mysqldump备份
#!/bin/bash

BACKUP_FILE="/backup/mysql/backup.sql.gz"
TEST_DB="test_restore"

# 1. 检查备份文件是否存在
if [ ! -f "$BACKUP_FILE" ]; then
    echo "备份文件不存在"
    exit 1
fi

# 2. 检查备份文件大小
FILE_SIZE=$(stat -f%z "$BACKUP_FILE" 2>/dev/null || stat -c%s "$BACKUP_FILE")
if [ $FILE_SIZE -lt 1000 ]; then
    echo "备份文件太小,可能损坏"
    exit 1
fi

# 3. 尝试恢复到测试数据库
mysql -u root -p -e "DROP DATABASE IF EXISTS $TEST_DB"
mysql -u root -p -e "CREATE DATABASE $TEST_DB"
gunzip < $BACKUP_FILE | mysql -u root -p $TEST_DB

# 4. 检查恢复结果
TABLE_COUNT=$(mysql -u root -p -N -e "SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA='$TEST_DB'")
if [ $TABLE_COUNT -eq 0 ]; then
    echo "恢复失败,没有表"
    exit 1
fi

echo "备份验证成功,共恢复 $TABLE_COUNT 个表"

# 5. 清理测试数据库
mysql -u root -p -e "DROP DATABASE $TEST_DB"

16.7.3 定期恢复演练

# 每月进行一次完整的恢复演练

# 1. 准备测试环境
# 2. 恢复最新的全量备份
# 3. 应用增量备份
# 4. 应用binlog
# 5. 验证数据完整性
# 6. 记录恢复时间
# 7. 编写演练报告

16.8 备份最佳实践

16.8.1 备份检查清单

✅ 备份策略已制定
✅ 备份脚本已编写
✅ 定时任务已配置
✅ 备份存储已规划
✅ 备份监控已部署
✅ 恢复流程已文档化
✅ 定期验证备份
✅ 定期恢复演练
✅ 异地备份已配置
✅ 备份加密已启用

16.8.2 常见错误

# ❌ 错误1:不验证备份
# 后果:需要恢复时发现备份损坏

# ❌ 错误2:只有一份备份
# 后果:备份损坏或丢失,无法恢复

# ❌ 错误3:备份和数据在同一磁盘
# 后果:磁盘损坏,备份和数据都丢失

# ❌ 错误4:没有异地备份
# 后果:机房故障,所有数据丢失

# ❌ 错误5:不测试恢复流程
# 后果:紧急恢复时手忙脚乱

# ❌ 错误6:备份没有加密
# 后果:备份泄露,数据安全风险

16.8.3 备份监控

# 监控备份是否成功
# 监控备份文件大小
# 监控备份时间
# 监控磁盘空间

# 告警规则:
# - 备份失败立即告警
# - 备份文件大小异常告警
# - 备份时间超时告警
# - 磁盘空间不足告警

16.9 本章总结

本章学习内容:

  • ✅ 备份的重要性
  • ✅ 备份类型(逻辑/物理、全量/增量、热/冷)
  • mysqldump逻辑备份 ⭐⭐⭐⭐⭐
  • ✅ mysqlpump逻辑备份
  • XtraBackup物理备份 ⭐⭐⭐⭐⭐
  • 备份策略设计 ⭐⭐⭐⭐⭐
  • 备份验证与测试 ⭐⭐⭐⭐⭐
  • ✅ 备份最佳实践

重点掌握:

  1. 没有备份就没有安全感
  2. mysqldump适合小数据库,XtraBackup适合大数据库
  3. 备份策略:3-2-1原则
  4. 必须定期验证和测试备份
  5. 备份和数据不能在同一磁盘
  6. 必须有异地备份

备份工具选择:

  • 小数据库(<10GB):mysqldump
  • 中大型数据库(>10GB):XtraBackup
  • 跨平台迁移:mysqldump
  • 快速恢复:XtraBackup

备份策略:

  • 小型:每天全量
  • 中型:每周全量 + 每天增量
  • 大型:每周全量 + 每天增量 + 每小时binlog

面试重点:

  • 备份的重要性
  • mysqldump和XtraBackup的区别
  • 如何设计备份策略
  • 如何验证备份
  • 3-2-1备份原则

下一章预告: 数据恢复实战


练习题

  1. 说明逻辑备份和物理备份的区别
  2. mysqldump的–single-transaction参数有什么作用?
  3. 如何使用mysqldump备份所有数据库?
  4. XtraBackup相比mysqldump有什么优势?
  5. 如何进行增量备份?
  6. 什么是3-2-1备份原则?
  7. 如何验证备份是否可用?
  8. 为什么要定期进行恢复演练?
  9. 设计一个中型数据库的备份策略
  10. 备份文件应该存储在哪里?

继续学习: 第17章:数据恢复实战