文章目录
- [1. 快速开始(应急备份)](#1. 快速开始(应急备份))
-
- [1.1 一键全量备份](#1.1 一键全量备份)
- [1.2 备份文件处理](#1.2 备份文件处理)
- [2. 基础方案:全量备份(mysqldump)](#2. 基础方案:全量备份(mysqldump))
-
- [2.1 导出命令与参数说明](#2.1 导出命令与参数说明)
- [2.2 压缩方式对比](#2.2 压缩方式对比)
- [2.3 大文件处理技巧](#2.3 大文件处理技巧)
- [2.4 恢复操作](#2.4 恢复操作)
- [2.5 局限性说明](#2.5 局限性说明)
- [3. 完整方案:全量 + 增量备份(binlog)](#3. 完整方案:全量 + 增量备份(binlog))
-
- [3.1 开启 binlog](#3.1 开启 binlog)
- [3.2 自动化备份脚本](#3.2 自动化备份脚本)
- [3.3 配置定时任务](#3.3 配置定时任务)
- [3.4 完整恢复流程](#3.4 完整恢复流程)
- [4. 企业级方案:云原生备份(推荐)](#4. 企业级方案:云原生备份(推荐))
-
- [4.1 阿里云混合云备份服务(HBR)](#4.1 阿里云混合云备份服务(HBR))
- [4.2 阿里云 RDS(长期考虑)](#4.2 阿里云 RDS(长期考虑))
- [5. 方案对比与选择建议](#5. 方案对比与选择建议)
-
- [5.1 RPO/RTO 对比表](#5.1 RPO/RTO 对比表)
- [5.2 决策树](#5.2 决策树)
- [5.3 推荐路径](#5.3 推荐路径)
- [6. 最佳实践](#6. 最佳实践)
-
- [6.1 备份文件命名规范](#6.1 备份文件命名规范)
- [6.2 异地备份](#6.2 异地备份)
- [6.3 恢复演练](#6.3 恢复演练)
- [6.4 监控告警](#6.4 监控告警)
- 附录
-
- 附录A:常用命令速查表
- 附录B:故障恢复示例(删库场景)
- [附录C:常见问题 FAQ](#附录C:常见问题 FAQ)
文档版本 : v1.0
适用场景 :ECS自建MySQL(8.0.44)
最后更新 :2026-03-21
1. 快速开始(应急备份)
适用场景:刚接手项目、紧急备份、临时导出数据
1.1 一键全量备份
# 最简命令(导出 trade 数据库)
mysqldump -u root -p trade | gzip > backup_$(date +%Y%m%d).sql.gz
# 输入密码后等待完成
参数说明:
-u root:数据库用户名-p:执行后输入密码(安全,不会在命令历史中暴露)| gzip:管道压缩,直接生成压缩文件$(date +%Y%m%d):自动添加日期,如backup_20260321.sql.gz
1.2 备份文件处理
下载到本地
# 从服务器下载备份文件
scp root@服务器IP:/root/backup_20260321.sql.gz ./
查看压缩包内容(不解压)
# 查看前100行
gunzip -c backup_20260321.sql.gz | head -100
# 查看有哪些表
gunzip -c backup_20260321.sql.gz | grep "CREATE TABLE" | awk '{print $3}'
# 查看文件结尾(确认备份完整性)
gunzip -c backup_20260321.sql.gz | tail -20
2. 基础方案:全量备份(mysqldump)
适用场景:数据量不大、允许一定数据丢失、作为日常备份基础
2.1 导出命令与参数说明
# 推荐命令(包含存储过程、触发器、事件)
mysqldump -u root -p \
--single-transaction \ # InnoDB一致性备份,不锁表
--routines \ # 备份存储过程
--triggers \ # 备份触发器
--events \ # 备份事件
--master-data=2 \ # 记录binlog位置(注释形式)
trade | gzip > trade_backup_$(date +%Y%m%d_%H%M%S).sql.gz
参数详解:
| 参数 | 作用 | 是否必须 |
|---|---|---|
--single-transaction |
保证数据一致性,不锁表 | ✅ 推荐(InnoDB) |
--routines |
备份存储过程和函数 | ⚠️ 如果有则必须 |
--triggers |
备份触发器 | ⚠️ 如果有则必须 |
--events |
备份事件调度器 | ⚠️ 如果有则必须 |
--master-data=2 |
记录备份时的binlog位置 | ✅ 用于增量恢复 |
--all-databases |
备份所有数据库 | 按需使用 |
2.2 压缩方式对比
| 压缩方式 | 命令 | 压缩率 | 速度 | 兼容性 |
|---|---|---|---|---|
| 无压缩 | mysqldump > backup.sql |
100% | 最快 | ✅ 通用 |
| gzip | `mysqldump | gzip > backup.sql.gz` | 10-20% | 快 |
| pigz(并行) | `mysqldump | pigz > backup.sql.gz` | 10-20% | 非常快 |
| bzip2 | `mysqldump | bzip2 > backup.sql.bz2` | 8-15% | 慢 |
推荐 :日常使用 gzip,压缩率和速度均衡,兼容性好。
安装 pigz(多核加速):
# CentOS/RHEL
yum install pigz
# Ubuntu/Debian
apt install pigz
2.3 大文件处理技巧
当备份文件过大(如 7GB)时,普通编辑器无法打开,推荐以下方法:
方法一:在服务器上直接分析
# 查看表列表
gunzip -c backup.sql.gz | grep "CREATE TABLE" | awk '{print $3}' | tr -d '`'
# 查看特定表结构
gunzip -c backup.sql.gz | grep -A 20 "CREATE TABLE \`users\`"
# 分页查看
gunzip -c backup.sql.gz | less
方法二:分割文件
# 按大小分割(每500MB一个)
gunzip -c backup.sql.gz | split -b 500M - backup_part_
# 下载小文件到本地
scp root@IP:/root/backup_part_* ./
方法三:恢复到测试库查看
# 创建测试数据库
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS trade_restore;"
# 恢复数据
gunzip -c backup.sql.gz | mysql -u root -p trade_restore
# 用 Navicat/DBeaver 等工具连接查看
2.4 恢复操作
# 步骤1:创建数据库(指定字符集避免乱码)
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS trade CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
# 步骤2:导入数据
gunzip -c backup.sql.gz | mysql -u root -p trade
# 或者分两步
gunzip backup.sql.gz
mysql -u root -p trade < backup.sql
2.5 局限性说明
全量备份只能恢复到备份完成那一刻的数据状态。
周一 02:00 全量备份(备份到周一的数据)
周二 10:00 新增100条订单
周三 15:00 新增200条订单
周四 09:00 数据库被误删
↓
周二、周三的数据全部丢失!
结论:仅靠全量备份无法实现"完全恢复",需要配合增量备份(binlog)。
3. 完整方案:全量 + 增量备份(binlog)
适用场景:需要恢复到任意时间点、核心业务数据
3.1 开启 binlog
检查当前状态
SHOW VARIABLES LIKE 'log_bin';
-- 如果显示 OFF,需要开启
配置 binlog
编辑 MySQL 配置文件(/etc/my.cnf 或 /etc/mysql/mysql.conf.d/mysqld.cnf):
[mysqld]
log-bin = /var/lib/mysql/mysql-bin # binlog 文件路径
binlog-format = ROW # 推荐 ROW 格式
expire_logs_days = 7 # 本地保留7天
server-id = 1 # 必须设置唯一ID
重启 MySQL
systemctl restart mysqld # CentOS/RHEL
service mysql restart # Ubuntu/Debian
验证是否开启
SHOW VARIABLES LIKE 'log_bin';
-- 应显示 ON
SHOW MASTER STATUS;
-- 应显示当前 binlog 文件及位置
3.2 自动化备份脚本
准备工作:配置免密登录
创建 /root/.my.cnf 配置文件:
[client]
user=root
password=你的数据库密码
chmod 600 /root/.my.cnf # 设置权限,仅root可读
脚本1:每周全量备份
创建 /root/scripts/weekly_full_backup.sh:
#!/bin/bash
# 每周全量备份脚本
BACKUP_DIR="/data/backup/mysql/full"
DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE="/var/log/mysql_backup.log"
# 创建备份目录
mkdir -p $BACKUP_DIR
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 开始全量备份..." >> $LOG_FILE
# 记录备份时的 binlog 位置
mysql --defaults-extra-file=/root/.my.cnf -e "FLUSH TABLES WITH READ LOCK; SHOW MASTER STATUS;" > /tmp/binlog_pos.txt
# 执行全量备份
mysqldump --defaults-extra-file=/root/.my.cnf \
--single-transaction \
--master-data=2 \
--all-databases \
--routines \
--triggers \
--events \
| gzip > $BACKUP_DIR/full_backup_$DATE.sql.gz
# 解锁表
mysql --defaults-extra-file=/root/.my.cnf -e "UNLOCK TABLES;"
# 保存 binlog 位置信息
cp /tmp/binlog_pos.txt $BACKUP_DIR/full_backup_$DATE_binlog_pos.txt
# 删除90天前的备份
find $BACKUP_DIR -name "full_backup_*.sql.gz" -mtime +90 -delete
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 全量备份完成: full_backup_$DATE.sql.gz" >> $LOG_FILE
脚本2:每天 binlog 备份
创建 /root/scripts/binlog_backup.sh:
#!/bin/bash
# binlog 增量备份脚本
BINLOG_SRC="/var/lib/mysql"
BACKUP_DIR="/data/backup/mysql/binlog"
DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE="/var/log/mysql_backup.log"
mkdir -p $BACKUP_DIR
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 开始 binlog 备份..." >> $LOG_FILE
# 刷新 binlog,产生新文件
mysql --defaults-extra-file=/root/.my.cnf -e "FLUSH LOGS;"
# 获取当前正在写入的 binlog 文件
CURRENT_BINLOG=$(mysql --defaults-extra-file=/root/.my.cnf -e "SHOW MASTER STATUS;" | grep -v File | awk '{print $1}')
# 复制已关闭的 binlog 文件到备份目录
for binlog in $BINLOG_SRC/mysql-bin.[0-9]*; do
if [ -f "$binlog" ]; then
filename=$(basename $binlog)
# 跳过当前正在写入的文件
if [ "$filename" != "$CURRENT_BINLOG" ]; then
cp $binlog $BACKUP_DIR/
# 压缩已备份的文件
gzip $BACKUP_DIR/$filename
fi
fi
done
# 删除30天前的 binlog 备份
find $BACKUP_DIR -name "mysql-bin.*.gz" -mtime +30 -delete
echo "[$(date '+%Y-%m-%d %H:%M:%S')] binlog 备份完成" >> $LOG_FILE
赋予执行权限
chmod +x /root/scripts/weekly_full_backup.sh
chmod +x /root/scripts/binlog_backup.sh
3.3 配置定时任务
# 编辑 crontab
crontab -e
添加以下内容:
# 每周日凌晨2点执行全量备份
0 2 * * 0 /root/scripts/weekly_full_backup.sh
# 每天凌晨1点执行 binlog 备份
0 1 * * * /root/scripts/binlog_backup.sh
# 可选:每小时备份一次 binlog(数据变化频繁时)
# 0 * * * * /root/scripts/binlog_backup.sh
3.4 完整恢复流程
场景:最后一次全量备份:3月20日 02:00,误删数据:3月21日 10:00,需要恢复到 3月21日 09:59:59
步骤1:恢复全量备份
# 找到最新的全量备份
ls -lh /data/backup/mysql/full/
# 恢复全量备份
gunzip -c /data/backup/mysql/full/full_backup_20260320_020000.sql.gz | mysql -u root -p
步骤2:查看备份时的 binlog 位置
# 查看备份文件中记录的 binlog 位置
grep "CHANGE MASTER" /data/backup/mysql/full/full_backup_20260320_020000.sql.gz | gunzip -c | head -1
# 输出示例:
# -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000123', MASTER_LOG_POS=456789;
步骤3:应用 binlog 增量
# 应用从备份位置到故障前的所有 binlog
mysqlbinlog \
--start-position=456789 \
--stop-datetime="2026-03-21 09:59:59" \
/data/backup/mysql/binlog/mysql-bin.000123 \
/data/backup/mysql/binlog/mysql-bin.000124 \
/data/backup/mysql/binlog/mysql-bin.000125 \
| mysql -u root -p
验证恢复结果
-- 检查关键表的数据
SELECT COUNT(*) FROM orders WHERE create_time > '2026-03-20';
4. 企业级方案:云原生备份(推荐)
适用场景:不想自己维护备份脚本、需要更高可靠性
4.1 阿里云混合云备份服务(HBR)
适用场景:
-
✅ ECS 上自建的 MySQL
-
✅ 本地机房的数据库
-
✅ 其他云平台的数据库
-
❌ 不适用于 RDS(RDS 有独立备份功能)
架构图
┌─────────────────────────────────────────────┐
│ 阿里云控制台(统一管理) │
└─────────────────────────────────────────────┘
↑
│ 管理/监控
↓
┌─────────────────────────────────────────────┐
│ 你的 ECS 服务器(自建 MySQL) │
│ ┌─────────────────────────────────────┐ │
│ │ HBR 客户端(需安装) │ │
│ │ ↓ │ │
│ │ 自建 MySQL(8.0.44) │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
│
│ 备份数据
↓
┌─────────────────────────────────────────────┐
│ 阿里云备份库(独立存储) │
│ - 自动增量备份 │
│ - 支持任意时间点恢复 │
│ - 数据多重备份,高可靠 │
└─────────────────────────────────────────────┘
安装配置步骤
第一步:开通服务
- 登录阿里云控制台
- 搜索"混合云备份服务"或"HBR"
- 开通服务(通常有免费额度)
第二步:安装客户端
在ECS服务器上安装HBR客户端:
# 下载客户端(在控制台获取具体链接)
wget https://hbr-client.oss-cn-hangzhou.aliyuncs.com/hbr-client-linux.tar.gz
# 解压并安装
tar -xzf hbr-client-linux.tar.gz
cd hbr-client-linux
./install.sh
# 按提示输入控制台生成的注册码,完成注册
第三步:配置备份策略
在控制台配置:
- 备份来源:选择"ECS自建MySQL"
- 备份内容 :选择要备份的数据库(如
trade) - 全量备份:每周一次
- 增量备份:每天一次
- 日志备份:每5分钟(可实现分钟级恢复)
- 保留周期:30天
第四步:测试恢复
- 在控制台选择"恢复"
- 可恢复到原ECS、新ECS或任意时间点
费用估算
| 计费项 | 价格(参考) |
|---|---|
| 备份存储费 | 约 0.15-0.3 元/GB/月 |
| 恢复流量费 | 同地域免费 |
以7GB数据库为例:
- 首次全量:7GB
- 每天增量:约 500MB
- 月存储费用 ≈ (7GB + 15GB) × 0.2元 ≈ 4.4元/月
4.2 阿里云 RDS(长期考虑)
如果未来预算允许,迁移到 RDS 是最省心的选择:
| 功能 | 自建 MySQL | RDS |
|---|---|---|
| 自动备份 | 需自己配置 | ✅ 开箱即用 |
| 任意时间点恢复 | 需手动应用binlog | ✅ 一键恢复 |
| 高可用 | 需自己搭建 | ✅ 自动切换 |
| 监控告警 | 需自己配置 | ✅ 内置 |
5. 方案对比与选择建议
5.1 RPO/RTO 对比表
| 方案 | RPO(数据丢失量) | RTO(恢复时间) | 复杂度 | 成本 |
|---|---|---|---|---|
| 仅每周全量备份 | 最多7天 | 数小时 | 低 | 免费 |
| 全量+每天binlog | 最多24小时 | 1-2小时 | 中 | 免费(存储成本) |
| 全量+实时binlog | 最多几分钟 | 1-2小时 | 中高 | 免费(存储成本) |
| HBR 云备份 | 最多5分钟 | 数十分钟 | 低 | 约5-20元/月 |
| RDS 云数据库 | 秒级 | 分钟级 | 极低 | 实例费用 |
5.2 决策树
数据重要性如何?
│
├── 非核心/可重建
│ └── 方案一:每周全量备份
│
├── 一般业务(允许丢失几小时数据)
│ └── 方案二:全量 + 每天binlog
│
├── 核心业务(允许丢失分钟级数据)
│ └── 方案三:全量 + 实时binlog 或 HBR
│
└── 关键交易系统(零数据丢失要求)
└── 方案四:RDS + 异地备份
5.3 推荐路径
| 阶段 | 推荐方案 | 理由 |
|---|---|---|
| 本周(应急) | 全量备份 + 手动binlog备份 | 快速建立基础保障 |
| 本月(规范化) | HBR 混合云备份 | 省心、可靠、成本低 |
| 长期(优化) | 评估是否需要迁移到 RDS | 业务增长后的选择 |
6. 最佳实践
6.1 备份文件命名规范
格式:{类型}_{数据库名}_{日期}_{时间}.{压缩格式}
示例:
full_trade_20260321_020000.sql.gz # 全量备份
binlog_mysql-bin.000123_20260321.sql.gz # binlog备份
命名要素:
- 类型标识(full/binlog)
- 数据库名
- 日期时间(便于排序和查找)
- 压缩格式(gz/bz2)
6.2 异地备份
原则 :备份不要和原始数据放在同一台服务器,否则服务器被黑/硬盘损坏时备份也会丢失。
方案A:同步到阿里云 OSS
# 安装 ossutil
wget https://gosspublic.alicdn.com/ossutil/1.7.18/ossutil64
chmod 755 ossutil64
./ossutil64 config
# 在备份脚本最后添加上传命令
./ossutil64 cp /data/backup/mysql/ oss://your-bucket/mysql_backup/ --recursive
方案B:同步到另一台 ECS
# 使用 rsync 同步
rsync -avz -e ssh /data/backup/mysql/ backup_user@另一台IP:/data/backup/
方案C:使用 HBR(自动异地)
HBR 默认将备份数据存储在阿里云备份库,天然具备异地冗余特性。
6.3 恢复演练
重要:备份的价值在于"能恢复"。建议每季度执行一次恢复演练。
# 恢复演练检查清单
1. 选择最近一次全量备份
2. 恢复到测试环境(另一台服务器或 Docker)
3. 验证关键表数据量
4. 验证应用连接测试
5. 记录恢复耗时
6. 填写演练报告
恢复演练模板:
| 项目 | 内容 |
|---|---|
| 演练日期 | 2026-03-21 |
| 使用的备份 | full_trade_20260320.sql.gz |
| 恢复目标时间 | 2026-03-20 02:00:00 |
| 实际恢复耗时 | 25分钟 |
| 数据验证结果 | ✅ 订单表 12,345 条,用户表 567 条 |
| 问题记录 | 无 |
| 演练结论 | 备份可用,恢复流程正确 |
6.4 监控告警
在备份脚本中加入失败告警:
# 检查备份是否成功
if [ $? -eq 0 ]; then
echo "备份成功"
else
echo "备份失败"
# 发送告警(钉钉/企业微信/邮件)
curl -X POST "https://your-webhook" \
-H "Content-Type: application/json" \
-d '{"msgtype": "text", "text": {"content": "MySQL备份失败!请检查服务器。"}}'
fi
告警内容建议包含:
- 备份类型(全量/binlog)
- 失败时间
- 服务器IP
- 错误信息(如有)
附录
附录A:常用命令速查表
| 操作 | 命令 |
|---|---|
| 全量备份(压缩) | `mysqldump -u root -p trade |
| 恢复(从压缩文件) | `gunzip -c backup.sql.gz |
| 查看备份内容 | `gunzip -c backup.sql.gz |
| 查看表列表 | `gunzip -c backup.sql.gz |
| 检查 binlog 状态 | mysql -u root -p -e "SHOW VARIABLES LIKE 'log_bin';" |
| 查看 binlog 文件 | mysql -u root -p -e "SHOW MASTER STATUS;" |
| 刷新 binlog | mysql -u root -p -e "FLUSH LOGS;" |
| 查看备份文件大小 | ls -lh backup.sql.gz |
| 下载备份文件 | scp root@IP:/path/backup.sql.gz ./ |
附录B:故障恢复示例(删库场景)
场景 :误执行 DROP DATABASE trade;
恢复步骤:
# 1. 停止应用,防止产生新数据
systemctl stop your-app
# 2. 找到最近的全量备份
ls -lh /data/backup/mysql/full/
# 3. 恢复全量备份
gunzip -c /data/backup/mysql/full/full_backup_20260320.sql.gz | mysql -u root -p
# 4. 查看全量备份时的 binlog 位置
grep "CHANGE MASTER" /data/backup/mysql/full/full_backup_20260320.sql.gz | gunzip -c
# 5. 查找误删操作的时间点
mysqlbinlog /data/backup/mysql/binlog/mysql-bin.000124 | grep -n "DROP DATABASE"
# 6. 应用 binlog 到误删前一刻
mysqlbinlog \
--start-position=456789 \
--stop-datetime="2026-03-21 09:59:59" \
/data/backup/mysql/binlog/mysql-bin.000123 \
/data/backup/mysql/binlog/mysql-bin.000124 \
| mysql -u root -p
# 7. 验证数据恢复
mysql -u root -p -e "SELECT COUNT(*) FROM trade.orders;"
# 8. 启动应用
systemctl start your-app
附录C:常见问题 FAQ
Q1:备份文件太大,磁盘空间不足怎么办?
A:三个解决方案:
- 使用压缩(gzip 可压缩到 10-20%)
- 备份后立即同步到 OSS 并删除本地文件
- 使用 HBR 备份到云端,不占用本地磁盘
Q2:恢复时提示"ERROR 1419"怎么办?
A:这是函数/触发器相关错误,恢复时添加 --force 参数:
mysql -u root -p --force trade < backup.sql
Q3:如何备份单个表?
A:
mysqldump -u root -p trade users | gzip > users_backup.sql.gz
Q4:如何验证备份文件是否损坏?
A:
# 检查文件完整性
gunzip -t backup.sql.gz && echo "文件完整" || echo "文件损坏"
# 尝试恢复前100行测试
gunzip -c backup.sql.gz | head -100 | mysql -u root -p test_db
文档维护:请根据实际情况更新数据库密码、备份路径等信息。如有问题,请联系文档维护者。