MySQL备份与恢复-数据安全的最后防线

一、为什么需要备份?

数据库备份是数据安全的最后防线,任何意外都可能导致数据丢失。

1.1 数据丢失风险

1
2
3
4
5
6
7
8
9
10
11
12
┌─────────────────────────────────────────────────────────────────┐
│ 数据丢失原因 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 💻 硬件故障 → 硬盘损坏、服务器宕机 │
│ 🦠 人为失误 → 误删数据、误操作 │
│ 🐛 软件错误 → 程序BUG导致数据损坏
│ 🦹 恶意攻击 → 黑客攻击、勒索病毒 │
│ 🌋 自然灾害 → 机房故障、火宅等 │
│ 🔄 升级失败 → 数据库升级失败 │
│ │
└─────────────────────────────────────────────────────────────────┘

1.2 备份策略

策略 说明 频率 适用场景
全量备份 备份所有数据 每天 小型数据库
增量备份 备份新增数据 每小时 大型数据库
差异备份 备份与全量的差异 每天 中型数据库

二、备份工具介绍

2.1 常用工具

工具 类型 特点
mysqldump 逻辑备份 跨版本、通用性强
mysqlpump 逻辑备份 并行备份、速度更快
mydumper 逻辑备份 多线程、热备份
xtrabackup 物理备份 热备份、增量支持
mysqlbackup 物理备份 Oracle官方工具

2.2 工具对比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌─────────────────────────────────────────────────────────────────┐
│ 备份工具对比 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ mysqldump │
│ ✅ 优点:简单、跨版本、备份文件小 │
│ ❌ 缺点:慢、大数据量不适合 │
│ │
│ mydumper │
│ ✅ 优点:多线程、热备、可并行 │
│ ❌ 缺点:需要安装 │
│ │
│ xtrabackup │
│ ✅ 优点:热备、增量快、在线备份 │
│ ❌ 缺点:只支持InnoDB/XtraDB
│ │
└─────────────────────────────────────────────────────────────────┘

三、mysqldump备份

3.1 基本使用

1
2
3
4
5
6
7
8
9
10
11
# 备份单个数据库
mysqldump -uroot -p mydb > mydb.sql

# 备份多个数据库
mysqldump -uroot -p --databases db1 db2 > dbs.sql

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

# 备份指定表
mysqldump -uroot -p mydb users orders > tables.sql

3.2 常用参数

1
2
3
4
5
6
7
8
9
10
11
12
13
# 常用参数
-uroot # 用户名
-p # 密码(不建议直接写密码)
--single-transaction # 事务备份(InnoDB)
--lock-tables # 锁表备份(MyISAM)
--routines # 备份存储过程
--triggers # 备份触发器
--events # 备份事件
--master-data # 记录binlog位置(用于主从)
--flush-logs # 刷新日志
--quick # 快速备份(大表)
--set-charset # 设置字符集
--default-character-set=utf8mb4 # 指定字符集

3.3 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 完整备份(InnoDB推荐)
mysqldump -uroot -p \
--single-transaction \
--routines \
--triggers \
--events \
--master-data=2 \
--flush-logs \
mydb > mydb_$(date +%Y%m%d).sql

# 压缩备份
mysqldump -uroot -p mydb | gzip > mydb_$(date +%Y%m%d).sql.gz

# 备份并记录binlog位置
mysqldump -uroot -p \
--single-transaction \
--master-data=2 \
--flush-logs \
mydb > mydb_backup.sql

# 备份结构(不包含数据)
mysqldump -uroot -p --no-data mydb > mydb_schema.sql

# 备份数据(不包含结构)
mysqldump -uroot -p --no-tablespaces mydb > mydb_data.sql

四、mysqlpump备份

4.1 基本使用

1
2
3
4
5
6
7
8
9
10
# 安装(如果未安装)
# apt install mysql-client

# 使用mysqlpump
mysqlpump -uroot -p mydb > mydb.sql

# 并行备份(加快速度)
mysqlpump -uroot -p \
--default-parallelism=4 \
--databases mydb > mydb.sql

4.2 特点

1
2
3
4
5
6
7
8
9
10
11
# 优点:
# 1. 多线程备份,速度更快
# 2. 可以备份多个数据库并行
# 3. 支持压缩输出
# 4. 可以排除表

# 示例:排除指定表
mysqlpump -uroot -p \
--exclude-databases=information_schema \
--exclude-tables=test% \
--databases mydb > mydb.sql

五、物理备份(xtrabackup)

5.1 安装

1
2
3
4
5
6
7
8
# Ubuntu/Debian
sudo apt install xtrabackup

# CentOS/RHEL
sudo yum install percona-xtrabackup

# 检查安装
xtrabackup --version

5.2 全量备份

1
2
3
4
5
6
7
8
9
10
11
12
# 创建备份目录
sudo mkdir -p /backup/full
sudo chown -R mysql:mysql /backup

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

# 备份完成后检查
ls -la /backup/full

5.3 增量备份

1
2
3
4
5
6
7
8
9
10
11
12
13
# 第一次增量备份(基于全量)
xtrabackup --backup \
--target-dir=/backup/inc1 \
--incremental-basedir=/backup/full \
--user=root \
--password=your_password

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

5.4 备份恢复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1. 准备恢复(应用日志)
xtrabackup --prepare --target-dir=/backup/full

# 如果有增量,需要依次prepare
xtrabackup --prepare --target-dir=/backup/full \
--incremental-dir=/backup/inc1

# 2. 停止MySQL
sudo systemctl stop mysql

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

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

# 5. 设置权限
sudo chown -R mysql:mysql /var/lib/mysql

# 6. 启动MySQL
sudo systemctl start mysql

六、逻辑备份(mydumper)

6.1 安装

1
2
3
4
5
6
7
8
# Ubuntu/Debian
sudo apt install mydumper

# CentOS/RHEL
sudo yum install mydumper

# 验证
mydumper --version

6.2 备份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 备份单个数据库
mydumper -u root -p password \
-o /backup/mydumper \
-B mydb

# 备份所有数据库
mydumper -u root -p password \
-o /backup/mydumper \
-A

# 多线程备份
mydumper -u root -p password \
-o /backup/mydumper \
-B mydb \
-t 4 # 4个线程

6.3 恢复

1
2
3
4
5
6
7
8
9

myloader -u root -p password \
-# 恢复数据库d /backup/mydumper \
-B mydb

# 恢复所有数据库
myloader -u root -p password \
-d /backup/mydumper \
-A

七、数据恢复

7.1 恢复SQL文件

1
2
3
4
5
6
7
8
# 恢复数据库
mysql -uroot -p mydb < mydb.sql

# 恢复压缩的备份
gunzip < mydb.sql.gz | mysql -uroot -p mydb

# 恢复所有数据库
mysql -uroot -p < all.sql

7.2 恢复指定表

1
2
3
4
5
6
7
8
# 从备份文件中提取指定表
sed -n '/CREATE TABLE.*users/,/UNLOCK TABLES/p' mydb.sql > users_table.sql

# 或者使用grep
grep -A 50 'CREATE TABLE.*users' mydb.sql > users_table.sql

# 恢复指定表
mysql -uroot -p mydb < users_table.sql

7.3 基于时间点恢复

1
2
3
4
5
6
7
8
-- 1. 查看binlog
mysqlbinlog mysql-bin.000001 > binlog.sql

-- 2. 恢复指定时间点之前的数据
mysqlbinlog --stop-datetime="2026-02-14 10:00:00" mysql-bin.000001 | mysql -uroot -p

-- 3. 恢复指定时间点之后的数据
mysqlbinlog --start-datetime="2026-02-14 10:00:00" mysql-bin.000001 | mysql -uroot -p

7.4 恢复误删数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-- 场景:DELETE FROM users WHERE id > 1000; 误删

-- 方法1:从备份恢复
-- 1. 恢复备份
mysql -uroot -p mydb < mydb_backup.sql

-- 2. 恢复增量数据
mysqlbinlog mysql-bin.000001 | mysql -uroot -p

-- 方法2:使用binlog闪回(需要安装binlog2sql)
# 安装
pip install binlog2sql

# 分析binlog,生成反向SQL
python binlog2sql.py -h127.0.0.1 -P3306 -uroot -p'password' -d mydb -t users \
--start-file=mysql-bin.000001 --start-pos=1234 --stop-file=mysql-bin.000002 --stop-pos=5678 \
> flashback.sql

# 恢复
mysql -uroot -p mydb < flashback.sql

八、定时自动备份

8.1 备份脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/bash
# backup.sh

# 配置
DB_NAME="mydb"
DB_USER="root"
DB_PASS="password"
BACKUP_DIR="/backup"
DATE=$(date +%Y%m%d_%H%M%S)

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

# 备份
echo "Starting backup at $(date)"
mysqldump -u$DB_USER -p$DB_PASS \
--single-transaction \
--routines \
--triggers \
--events \
--master-data=2 \
--flush-logs \
$DB_NAME | gzip > $BACKUP_DIR/${DB_NAME}_${DATE}.sql.gz

# 删除7天前的备份
find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete

echo "Backup completed at $(date)"

8.2 添加定时任务

1
2
3
4
5
6
7
8
# 编辑crontab
crontab -e

# 添加定时任务(每天凌晨2点执行)
0 2 * * * /path/to/backup.sh >> /var/log/backup.log 2>&1

# 重启crontab
sudo systemctl restart cron

8.3 定时任务示例

1
2
3
4
5
6
7
8
# 每天凌晨2点全量备份
0 2 * * * /path/to/backup.sh

# 每周日凌晨3点全量备份
0 3 * * 0 /path/to/backup.sh

# 每天每小时增量备份(需要配置binlog)
0 * * * * /path/to/inc_backup.sh

九、备份验证

9.1 验证备份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 检查备份文件
ls -lh /backup/

# 检查备份文件完整性
gzip -t mydb_20260214.sql.gz

# 检查SQL文件
head -20 mydb_20260214.sql
tail -20 mydb_20260214.sql

# 测试恢复(恢复测试库)
mysql -uroot -p testdb < mydb_20260214.sql

# 检查数据
mysql -uroot -p -e "USE testdb; SELECT COUNT(*) FROM users;"

9.2 恢复演练

1
2
3
4
5
-- 定期进行恢复演练
-- 1. 在测试环境恢复备份
-- 2. 验证数据完整性
-- 3. 记录恢复时间
-- 4. 文档化恢复步骤

十、云备份方案

10.1 阿里云RDS

1
2
3
4
5
6
7
8
# 自动备份
-- 登录阿里云RDS控制台
-- 配置自动备份策略
-- 设置备份保留时间

# 手动备份
-- 手动创建备份
-- 下载备份文件

10.2 AWS RDS

1
2
3
4
5
6
7
8
9
# 自动备份
-- 默认开启自动备份
-- 可配置保留天数(1-35天)
-- 创建手动快照

# 从快照恢复
-- 进入RDS控制台
-- 选择快照
-- 恢复实例

10.3 自建+对象存储

1
2
3
4
5
6
7
# 备份到OSS/MinIO/S3
# 安装ossutil
# 配置访问密钥
# 同步备份文件

# 示例:备份到阿里云OSS
ossutil cp mydb_$(date +%Y%m%d).sql.gz oss://mybucket/backup/

十一、常见问题

11.1 备份文件太大

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 解决方案:
-- 1. 使用压缩
mysqldump ... | gzip > backup.sql.gz

-- 2. 排除大表
mysqldump -uroot -p mydb --ignore-table=mydb.logs > mydb.sql

-- 3. 分表备份
for table in $(mysql -uroot -p mydb -N -e "SHOW TABLES"); do
mysqldump -uroot -p mydb $table | gzip > ${table}.sql.gz
done

-- 4. 使用物理备份
xtrabackup ...

11.2 备份超时

1
2
3
4
5
6
7
8
9
-- 解决方案:
-- 1. 增加超时时间
mysqldump --single-transaction --quick ...

-- 2. 使用物理备份
xtrabackup ...

-- 3. 分段备份
-- 分时间段、分表备份

11.3 恢复失败

1
2
3
4
5
6
7
8
9
10
11
12
-- 常见错误:
-- 1. 字符集不匹配
-- 解决:指定字符集
mysql --default-character-set=utf8mb4 -uroot -p mydb < backup.sql

-- 2. 外键约束问题
-- 解决:暂时禁用外键检查
mysql -uroot -p --init-command="SET FOREIGN_KEY_CHECKS=0;" mydb < backup.sql

-- 3. 表已存在
-- 解决:先删除或使用DROP TABLE
mysqldump ... --add-drop-table ...

十二、备份策略建议

12.1 中小网站

备份类型 频率 保留时间
全量备份 每天 7天
Binlog 实时 3天

12.2 中大型网站

备份类型 频率 保留时间
全量备份 每天 30天
增量备份 每小时 7天
Binlog 实时 3天

12.3 核心业务

备份类型 频率 保留时间
全量备份 每天 90天
增量备份 每小时 7天
Binlog 实时 7天
异地备份 每天 30天

十三、监控与告警

13.1 备份监控

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 检查备份文件是否存在
[ -f /backup/mydb_$(date +%Y%m%d).sql.gz ] || echo "Backup failed!"

# 检查备份文件大小
SIZE=$(stat -c%s /backup/mydb_$(date +%Y%m%d).sql.gz)
if [ $SIZE -lt 1000 ]; then
echo "Backup file too small!"
fi

# 检查备份时间
LAST_BACKUP=$(stat -c %Y /backup/mydb_latest.sql.gz)
NOW=$(date +%s)
DIFF=$((NOW - LAST_BACKUP))
if [ $DIFF -gt 86400 ]; then
echo "Backup too old!"
fi

13.2 告警配置

1
2
3
4
5
6
7
# 配置企业微信/钉钉/邮件告警
# 在备份脚本中添加告警逻辑
if [ $? -ne 0 ]; then
curl -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=XXX" \
-H 'Content-Type: application/json' \
-d '{"msgtype": "text", "text": {"content": "Backup failed!"}}'
fi

参考资料


持续更新中…欢迎收藏!

#MySQL #备份 #恢复 #数据安全 #运维 #教程


MySQL备份与恢复-数据安全的最后防线
https://r0f2.my/post/30-mysql-backup-recovery/
作者
JA
发布于
2026年2月14日
许可协议