综合实验二 MySQL 备份恢复与灾难恢复综合实战
综合实验二 MySQL 备份恢复与灾难恢复综合实战
Section titled “综合实验二 MySQL 备份恢复与灾难恢复综合实战”🎯 本实验学习目标
- 能使用 mysqldump 完成全库备份、单库备份和单表备份
- 能模拟多种灾难场景并完成恢复操作
- 能利用 binlog 完成时间点恢复(PITR)
- 能设计并执行完整的备份策略方案
公司电商系统运行一段时间后,管理层意识到数据是核心资产。某天,发生了以下事件:
开发人员在调试时误删了
orders表中的所有数据;紧接着,运维工程师发现有人用 DROP 命令删除了products表。公司需要你制定备份策略并能在各种灾难场景下恢复数据。
任务一 备份策略设计与准备
Section titled “任务一 备份策略设计与准备”1.1 理解备份类型
Section titled “1.1 理解备份类型”| 备份方式 | 工具 | 特点 | 适用场景 |
|---|---|---|---|
| 全量逻辑备份 | mysqldump | 导出为 SQL 文件,可读性好 | 小中型数据库(< 50GB) |
| 全量物理备份 | xtrabackup / 数据文件复制 | 直接复制数据文件,速度快 | 大型数据库(> 50GB) |
| 增量备份 | binlog | 只记录数据变更事件 | 配合全量备份实现 PITR |
1.2 创建备份目录
Section titled “1.2 创建备份目录”# 在虚拟机中创建备份目录sudo mkdir -p /backup/fullsudo mkdir -p /backup/binlogsudo chown -R ly:ly /backup1.3 确认 binlog 已开启
Section titled “1.3 确认 binlog 已开启”sudo mysql
-- 确认 binlog 已开启SHOW VARIABLES LIKE 'log_bin'; -- 应为 ONSHOW VARIABLES LIKE 'binlog_format'; -- 应为 ROWSHOW VARIABLES LIKE 'binlog_expire_logs_seconds'; -- 应为 604800
-- 查看当前 binlog 文件和位置SHOW MASTER STATUS;任务二 执行全量备份
Section titled “任务二 执行全量备份”2.1 用 mysqldump 备份单个数据库
Section titled “2.1 用 mysqldump 备份单个数据库”这是最常用的备份方式——备份指定数据库的结构和数据:
# 备份 ecommerce 数据库sudo mysqldump -u root -p123456 \ --databases ecommerce \ --single-transaction \ --routines \ --triggers \ --events \ --set-gtid-purged=OFF \ > /backup/full/ecommerce_full_$(date +%Y%m%d_%H%M%S).sql参数说明:
| 参数 | 含义 |
|---|---|
--databases ecommerce | 指定备份的数据库,输出中包含 CREATE DATABASE 和 USE 语句 |
--single-transaction | InnoDB 一致性快照备份,不锁表(关键参数) |
--routines | 包含存储过程和函数 |
--triggers | 包含触发器 |
--events | 包含定时事件 |
--set-gtid-purged=OFF | 不输出 GTID 信息(单机环境推荐) |
2.2 用 mysqldump 备份所有数据库
Section titled “2.2 用 mysqldump 备份所有数据库”# 备份所有数据库(系统库 + 业务库)sudo mysqldump -u root -p123456 \ --all-databases \ --single-transaction \ --routines \ --triggers \ --events \ --set-gtid-purged=OFF \ > /backup/full/all_databases_$(date +%Y%m%d_%H%M%S).sql2.3 用 mysqldump 备份单张表
Section titled “2.3 用 mysqldump 备份单张表”# 只备份 orders 表sudo mysqldump -u root -p123456 \ ecommerce orders \ --single-transaction \ --set-gtid-purged=OFF \ > /backup/full/ecommerce_orders_$(date +%Y%m%d_%H%M%S).sql2.4 查看备份文件内容
Section titled “2.4 查看备份文件内容”# 查看备份文件头部(前 30 行)head -30 /backup/full/ecommerce_full_*.sql
# 查看备份文件大小ls -lh /backup/full/2.5 记录备份时的 binlog 位置
Section titled “2.5 记录备份时的 binlog 位置”sudo mysql
-- 切换 binlog,让备份后的操作记录到新文件FLUSH BINARY LOGS;
-- 记录当前 binlog 位置SHOW MASTER STATUS;输出类似:
+------------------+----------+| File | Position |+------------------+----------+| mysql-bin.000003 | 157 |+------------------+----------+任务三 灾难场景模拟与恢复
Section titled “任务三 灾难场景模拟与恢复”场景一 误删表数据(DELETE)——用 binlog 恢复
Section titled “场景一 误删表数据(DELETE)——用 binlog 恢复”sudo mysqlUSE ecommerce;
-- 记录当前数据量SELECT COUNT(*) AS '恢复前订单数' FROM orders;SELECT COUNT(*) AS '恢复前用户数' FROM users;
-- 正常业务操作:新增一笔订单INSERT INTO orders (user_id, product_id, quantity, total_amount, order_status)VALUES (2, 1, 1, 299.00, 0);
-- 记录这条正常操作的时间SELECT NOW() AS '正常操作时间';
-- 灾难发生:误删 orders 表所有数据!DELETE FROM orders;SELECT COUNT(*) AS '误删后订单数' FROM orders; -- 结果:0第 1 步:立即停止业务写入(课堂模拟中跳过,实际生产必须执行)
第 2 步:找到误操作在 binlog 中的位置
# 查看最新的 binlog 文件sudo mysql -u root -p123456 -e "SHOW BINARY LOGS;"
# 在 binlog 中搜索 DELETE 操作sudo mysqlbinlog --base64-output=DECODE-ROWS -v \ /var/lib/mysql/mysql-bin.000003 | grep -B 5 "DELETE FROM"典型输出如下:
# at 316#260603 10:09:21 server id 1 end_log_pos 382 CRC32 0xc46cad82 Table_map: `ecommerce`.`orders` mapped to number 92# has_generated_invisible_primary_key=0# at 382#260603 10:09:21 server id 1 end_log_pos 525 CRC32 0x3ed3165c Delete_rows: table id 92 flags: STMT_END_F### DELETE FROM `ecommerce`.`orders`# 更精确地查看该位置附近的内容sudo mysqlbinlog --base64-output=DECODE-ROWS -v \ --start-position=157 \ /var/lib/mysql/mysql-bin.000003 | less找到 INSERT 事件的结束位置和 DELETE 事件的起始位置:
# at 380 ← INSERT(正常操作)# at 316 ← DELETE 的 Table_map(误操作)← stop-position 用这个第 3 步:从备份恢复到备份时刻的状态
# 先用备份恢复(恢复到备份时的数据状态)sudo mysql -u root -p123456 < /backup/full/ecommerce_full_*.sql第 4 步:回放 binlog 到误操作前
# 回放 binlog:从备份位置到误操作之前sudo mysqlbinlog \ --start-position=157 \ --stop-position=580 \ --database=ecommerce \ /var/lib/mysql/mysql-bin.000003 | sudo mysql -u root -p123456第 5 步:验证恢复结果
sudo mysqlUSE ecommerce;
-- 验证数据恢复SELECT COUNT(*) AS '恢复后订单数' FROM orders;-- 应包含备份时的数据 + 误删前新增的那笔订单
-- 确认新增的订单已恢复SELECT * FROM orders ORDER BY order_id DESC LIMIT 3;场景二 误删表(DROP TABLE)——用全量备份 + binlog 恢复
Section titled “场景二 误删表(DROP TABLE)——用全量备份 + binlog 恢复”sudo mysqlUSE ecommerce;
-- 先补充一些新数据(模拟备份后的正常业务)INSERT INTO products (name, category, price, stock) VALUES ('蓝牙耳机', '数码配件', 199.00, 80), ('充电宝', '数码配件', 129.00, 300);
-- 记录正常数据插入的时间SELECT NOW() AS '正常操作时间';
-- 灾难发生:误执行了 DROP TABLE!DROP TABLE products;第 1 步:确认表已不存在
SHOW TABLES LIKE 'products';-- 预期:空结果集第 2 步:从备份恢复整个库
sudo mysql -u root -p123456 < /backup/full/ecommerce_full_*.sql第 3 步:回放 binlog 恢复备份后的正常操作
# 从备份记录的位置开始,回放到 DROP 操作之前# 假设 DROP 发生在位置 1200sudo mysqlbinlog \ --start-position=157 \ --stop-position=1200 \ --database=ecommerce \ /var/lib/mysql/mysql-bin.000003 | sudo mysql -u root -p123456第 4 步:验证恢复结果
sudo mysqlUSE ecommerce;
-- 确认 products 表已恢复SHOW TABLES;
-- 确认数据完整SELECT COUNT(*) AS '恢复后商品数' FROM products;SELECT * FROM products;
-- 确认备份后新增的商品也在SELECT * FROM products WHERE name IN ('蓝牙耳机', '充电宝');场景三 误删整个数据库——用全量备份恢复
Section titled “场景三 误删整个数据库——用全量备份恢复”sudo mysql
-- 灾难发生:误删整个数据库DROP DATABASE ecommerce;
-- 确认数据库已不存在SHOW DATABASES LIKE 'ecommerce';-- 预期:空结果集第 1 步:从备份恢复
# 备份文件中包含 CREATE DATABASE 和 USE 语句,直接导入即可sudo mysql -u root -p123456 < /backup/full/ecommerce_full_*.sql第 2 步:验证恢复结果
sudo mysql
-- 确认数据库已恢复SHOW DATABASES LIKE 'ecommerce';
USE ecommerce;
-- 确认所有表已恢复SHOW TABLES;
-- 确认数据完整SELECT COUNT(*) AS '用户数' FROM users;SELECT COUNT(*) AS '商品数' FROM products;SELECT COUNT(*) AS '订单数' FROM orders;
-- 抽样检查数据SELECT * FROM orders;任务四 Navicat 备份恢复演练
Section titled “任务四 Navicat 备份恢复演练”4.1 在 Navicat 中备份 ecommerce 数据库
Section titled “4.1 在 Navicat 中备份 ecommerce 数据库”- 打开 Navicat,连接到虚拟机 MySQL
- 右键
ecommerce数据库 → 转储 SQL 文件 → 结构和数据 - 保存为
D:\backup\ecommerce_navicat_$(日期).sql - 等待导出完成
4.2 在 Navicat 中还原到测试库
Section titled “4.2 在 Navicat 中还原到测试库”- 右键连接 → 新建数据库 → 名称:
ecommerce_restore_test,字符集utf8mb4 - 右键
ecommerce_restore_test→ 运行 SQL 文件 - 选择刚才导出的
.sql文件,执行 - 刷新数据库,验证表和数据:
SELECT COUNT(*) FROM ecommerce_restore_test.users;SELECT COUNT(*) FROM ecommerce_restore_test.products;SELECT COUNT(*) FROM ecommerce_restore_test.orders;4.3 验证备份有效性
Section titled “4.3 验证备份有效性”| 检查项 | 验证方式 | 预期结果 |
|---|---|---|
| 表结构完整 | SHOW TABLES; | 3 张表全部存在 |
| 数据行数一致 | COUNT(*) 逐表对比 | 与源库完全一致 |
| 外键约束完整 | SHOW CREATE TABLE orders; | 包含 FOREIGN KEY 定义 |
| 数据内容正确 | 抽样查询 | 数据与源库一致 |
任务五 备份策略方案设计
Section titled “任务五 备份策略方案设计”5.1 备份策略设计原则
Section titled “5.1 备份策略设计原则”| 因素 | 考虑点 |
|---|---|
| RPO(恢复点目标) | 最多能接受丢失多长时间的数据? |
| RTO(恢复时间目标) | 从故障到恢复上线,最多允许花多长时间? |
| 数据量 | 数据量越大,全量备份耗时越长 |
| 业务写入频率 | 写入越频繁,需要越频繁的增量备份 |
5.2 推荐备份策略
Section titled “5.2 推荐备份策略”小型数据库(< 10GB)策略
Section titled “小型数据库(< 10GB)策略”| 备份类型 | 频率 | 保留时间 | 工具 |
|---|---|---|---|
| 全量备份 | 每天凌晨 2:00 | 保留 7 天 | mysqldump + cron |
| binlog | 持续记录 | 保留 7 天 | MySQL 自动 |
中型数据库(10GB ~ 100GB)策略
Section titled “中型数据库(10GB ~ 100GB)策略”| 备份类型 | 频率 | 保留时间 | 工具 |
|---|---|---|---|
| 全量备份 | 每周日凌晨 2:00 | 保留 4 周 | mysqldump / xtrabackup |
| 增量(binlog) | 持续记录 | 保留 14 天 | MySQL 自动 |
5.3 自动备份脚本示例
Section titled “5.3 自动备份脚本示例”#!/bin/bash# 用途:每日自动备份 ecommerce 数据库
# 配置区BACKUP_DIR="/backup/full"DB_USER="root"DB_PASS="123456"DB_NAME="ecommerce"DATE=$(date +%Y%m%d_%H%M%S)KEEP_DAYS=7
# 创建备份sudo mysqldump -u "$DB_USER" -p"$DB_PASS" \ --databases "$DB_NAME" \ --single-transaction \ --routines --triggers --events \ --set-gtid-purged=OFF \ > "$BACKUP_DIR/${DB_NAME}_${DATE}.sql"
# 检查备份是否成功if [ $? -eq 0 ]; then echo "[$(date)] 备份成功:${DB_NAME}_${DATE}.sql" >> /var/log/mysql_backup.logelse echo "[$(date)] 备份失败!" >> /var/log/mysql_backup.logfi
# 清理过期备份find "$BACKUP_DIR" -name "${DB_NAME}_*.sql" -mtime +$KEEP_DAYS -delete配置定时任务(课堂实操):
# 第 1 步:将脚本保存到固定位置sudo mkdir -p /opt/scriptssudo nano /opt/scripts/mysql_backup.sh# 将上面的备份脚本内容粘贴进去,保存退出
# 第 2 步:赋予执行权限sudo chmod +x /opt/scripts/mysql_backup.sh
# 第 3 步:手动测试一次(确认脚本能正常运行)sudo /opt/scripts/mysql_backup.shls -lh /backup/full/
# 第 4 步:配置 cron 定时任务sudo crontab -e在 crontab 编辑器中添加以下内容:
# 每天凌晨 2:00 自动备份 ecommerce 数据库0 2 * * * /opt/scripts/mysql_backup.sh >> /var/log/mysql_backup.log 2>&1保存退出后验证 cron 是否生效:
# 查看当前用户的定时任务列表sudo crontab -l
# 确认 cron 服务正在运行sudo systemctl status croncron 时间格式速查:
| 字段 | 含义 | 取值范围 |
|---|---|---|
第 1 个 0 | 分钟 | 0 ~ 59 |
第 2 个 2 | 小时 | 0 ~ 23 |
第 3 个 * | 日 | 1 ~ 31 |
第 4 个 * | 月 | 1 ~ 12 |
第 5 个 * | 星期 | 0 ~ 7(0 和 7 都是周日) |
常见 cron 示例:
# 每天凌晨 2 点执行0 2 * * *
# 每周日凌晨 3 点执行0 3 * * 0
# 每 6 小时执行一次0 */6 * * *
# 每月 1 日凌晨 1 点执行0 1 1 * *| 任务 | 核心能力 | 关键验证点 |
|---|---|---|
| 任务一:备份策略设计 | 理解备份类型与适用场景 | 能说出 RPO 含义 |
| 任务二:全量备份 | mysqldump 三种粒度备份 | 3 个备份文件均已生成并验证 |
| 任务三:灾难恢复 | 三种场景的恢复流程 | 三种场景全部恢复成功 |
| 任务四:Navicat 备份恢复 | 图形化备份还原 | 备份还原验证通过 |
| 任务五:备份策略方案 | 自动化备份方案设计 | 脚本 + cron 可运行 |