MySQL 备份与恢复实战:mysqldump、XtraBackup 与 binlog 定点恢复

MySQL 备份与恢复实战:mysqldump、XtraBackup 与 binlog 定点恢复
神经蛙索引优化、事务锁、主从复制和分库分表能帮你“跑得快、扛得住”,但数据一旦误删、磁盘损坏或勒索软件加密,backup 才是最后一道防线。本文聚焦 MySQL 备份与恢复:从 mysqldump 到 XtraBackup,再到 binlog 定点恢复,把“能回滚”这件事讲透。
一、备份是最后一道防线
很多团队把备份当成“有就行”,直到出事才发现:
- 备份文件损坏,无法解压。
- 只备份了 schema,没备份数据。
- 恢复演练从没做过,真正恢复时耗时半天。
- binlog 没开,误删后只能回档到昨晚的全量。
所以备份的核心目标不只是“存一份数据”,而是在可接受的时间内,恢复到可接受的状态。
二、备份分类与策略
2.1 逻辑备份 vs 物理备份
| 维度 | 逻辑备份(mysqldump) | 物理备份(XtraBackup) |
|---|---|---|
| 形式 | SQL 文本 / CSV | 数据文件副本 |
| 速度 | 慢(逐行导出) | 快(拷贝页 + redo) |
| 体积 | 大,可压缩 | 接近原库,可压缩 |
| 恢复 | 逐条执行 SQL | 直接替换数据文件 |
| 适用 | 小库、跨版本、部分表 | 大库、生产全量、热备 |
| 一致性 | --single-transaction |
InnoDB 热备机制 |
2.2 全量、增量与差异
- 全量:每次备份完整数据。简单、恢复快,但占用空间大。
- 增量:只备份自上次备份后变化的数据。XtraBackup 基于 LSN(Log Sequence Number)实现。
- 差异:备份自上次全量以来的变化。介于两者之间,恢复时需要一次全量 + 一次差异。
生产常见组合:周全量 + 日增量 + 实时 binlog。
2.3 热备、温备与冷备
- 热备:应用不中断,InnoDB 可通过 XtraBackup 实现。
- 温备:只读锁表,MyISAM 常用。
- 冷备:停库复制数据文件,一般仅用于维护窗口。
XtraBackup 对 MyISAM 表备份时会短暂加锁,因此大量 MyISAM 的场景建议先迁到 InnoDB。
三、mysqldump 逻辑备份
3.1 最常用命令
1 | # 全库一致性备份 |
参数含义:
--single-transaction:在事务中导出,保证 InnoDB 一致性,不锁表。--master-data=2:记录 binlog 位点,注释形式写入备份文件,便于 PITR。--routines --triggers --events:导出存储过程、触发器、事件。--all-databases:全库。
3.2 单库 / 单表 / 只导结构
1 | # 单库 |
3.3 压缩与定时任务
全量 SQL 通常很大,导出时直接压缩:
1 | mysqldump -u root -p --single-transaction --all-databases \ |
配合 crontab 每日执行:
1 | 0 2 * * * /usr/local/bin/backup_mysql.sh >> /var/log/mysql_backup.log 2>&1 |
backup_mysql.sh 示例:
1 |
|
密码写在命令行里会暴露在 ps 中。更安全的做法是把账号密码放进 ~/.my.cnf 的 [mysqldump] 段,并设置 600 权限。
3.4 mydumper:并行逻辑备份
当库很大但暂时不想用物理备份时,可以用 mydumper 多线程导出:
1 | mydumper -u root -p -B db_name -t 4 -o /backup/dir |
-t 4:4 个线程。- 导出为多个文件,恢复用
myloader,可并发导入。
3.5 mysqldump 避坑
| 坑 | 说明 |
|---|---|
| 大表导出导致从库延迟 | 长事务会阻塞 purge,主从场景注意选择低峰期 |
--single-transaction 对 MyISAM 无效 |
MyISAM 会锁表,应改用 --lock-all-tables |
| 未压缩占满磁盘 | 大库务必备份时直接 gzip / pigz |
| 没记录 binlog 位点 | 缺少位点无法做 PITR |
| 权限不足 | 需 SELECT、RELOAD、LOCK TABLES、REPLICATION CLIENT |
四、XtraBackup 物理备份
XtraBackup(Percona XtraBackup)是 MySQL 物理热备的首选,基于 InnoDB 崩溃恢复机制,备份期间不阻塞读写。
4.1 全量备份
1 | # 1. 备份 |
4.2 增量备份
XtraBackup 增量基于 LSN:
1 | # 周日全量 |
恢复时,先把全量 prepare,再依次 apply 增量:
1 | xtrabackup --prepare --apply-log-only --target-dir=/backup/full/2026-09-06 |
4.3 流式压缩与远程备份
大库备份直接写本地磁盘可能撑满,可用流式输出:
1 | xtrabackup --backup --stream=xbstream --compress \ |
或直传远程:
1 | xtrabackup --backup --stream=xbstream \ |
4.4 mysqldump vs XtraBackup
| 场景 | 推荐工具 | 理由 |
|---|---|---|
| < 50GB,需跨版本/部分表 | mysqldump | 灵活、可读 |
| > 50GB,生产热备 | XtraBackup | 快、不锁表 |
| 需要增量/差异 | XtraBackup | 支持 LSN 增量 |
| 快速搭建从库 | XtraBackup + --slave-info |
直接复制数据目录 |
| 仅做 Schema 备份 | mysqldump --no-data |
文本 diff 友好 |
五、binlog 定点恢复(PITR)
binlog 在主从复制篇已经讲过,它是 MySQL 的逻辑变更日志。除了复制,binlog 另一个核心用途就是基于时间点的恢复(Point-in-Time Recovery, PITR)。
5.1 前置条件
要做 PITR,必须同时满足:
- 已开启 binlog:
log_bin = ON,建议binlog_format = ROW。 - 有全量或增量备份作为基线。
- 备份记录了 binlog 位点(mysqldump 的
--master-data=2或 XtraBackup 的xtrabackup_binlog_info)。
5.2 找到目标位点
误操作后,先别急着恢复。确定:
- 误操作执行的大致时间。
- 对应的 binlog 文件。
1 | SHOW BINARY LOGS; |
5.3 用 mysqlbinlog 恢复
假设周日凌晨 02:00 的全量备份位点是 mysql-bin.000015:156,而周三 14:30 误删了一张表。目标是把数据恢复到 14:29:59。
1 | mysqlbinlog \ |
参数说明:
--start-position:从备份记录的位点开始。--stop-datetime/--stop-position:恢复到误操作前一刻。- 可指定多个 binlog 文件,按顺序回放。
ROW 格式下,mysqlbinlog 默认输出 base64 事件。若需人工审计,可加 -v 或 --base64-output=DECODE-ROWS 转成伪 SQL。
5.4 误删库恢复实战流程
- 保护现场:立即停止业务写入,避免 binlog 被覆盖。
- 准备临时实例:用备份恢复一个独立实例,不要直接覆盖生产。
- 回放 binlog:在临时实例上执行
mysqlbinlog --stop-datetime恢复到误删前。 - 导出需要的数据:用 mysqldump 导出被删的库/表。
- 回灌生产:确认数据无误后,导入生产或做主从切换。
如果误操作是 DROP TABLE,PITR 能救回数据;但如果是 TRUNCATE TABLE 后又有新写入,目标表的数据需要单独导出再合并,不能简单回放。
5.5 binlog 恢复的常见坑
| 坑 | 避免方法 |
|---|---|
| 恢复时越过误操作 | 精确计算 --stop-datetime,宁可少恢复几秒 |
| 多个 binlog 文件顺序错 | 按文件名序号依次回放 |
| 表结构变更后回放失败 | 确保目标实例 schema 与备份时一致 |
| GTID 模式下重复执行 | 用 --skip-gtids 或 --include-gtids / --exclude-gtids 精确控制 |
GTID 模式下,mysqlbinlog 默认带 SET @@SESSION.GTID_NEXT。若只想恢复部分事件,可用 --exclude-gtids 跳过误操作事务。
六、生产备份架构
6.1 3-2-1 原则
- 3 份数据副本:生产数据 + 2 份备份。
- 2 种不同介质:本地磁盘 + 对象存储 / 磁带。
- 1 份异地:跨可用区或跨地域。
6.2 延迟从库
延迟从库是防御误删的神器:
1 | CHANGE MASTER TO MASTER_DELAY = 3600; |
设置 1 小时延迟后,主库误删表时,从库还有 1 小时前的数据,可直接在从库上导出恢复,省去全量 + binlog 回放的漫长等待。
6.3 备份校验与演练
备份不校验等于没备:
- 定期恢复演练:每周/每月用备份在临时环境做一次全量恢复。
- 校验文件完整性:对比 md5、检查压缩包能否解压。
- 校验数据一致性:恢复后跑几条关键查询,对比记录数、checksum。
- 监控备份任务:cron 失败告警、备份文件大小异常告警。
6.4 云 RDS 自动备份
如果使用阿里云 RDS、AWS RDS 等托管服务,通常已提供:
- 自动全量快照。
- 自动 binlog 备份。
- 按时间点恢复控制台。
但即便如此,也建议额外做逻辑导出,防止云账号异常、区域故障或误操作控制台删除实例。
七、避坑清单
- [ ] 不要只备份数据文件,忽略 binlog。
- [ ] 不要只开 binlog,却不做全量基线。
- [ ] 不要把备份和数据库放在同一块磁盘。
- [ ] 不要备份到生产服务器本地就不管,至少同步到对象存储。
- [ ] 不要高估备份文件,恢复演练要定期开展。
- [ ] 不要给备份脚本 root 密码明文,使用专用备份账号和
.my.cnf。 - [ ] 不要忽视权限,备份账号需最小权限原则。
- [ ] 不要在恢复时直接覆盖生产,先在临时实例验证。
总结
MySQL 备份没有银弹,但有标准答案:
- 小库 / 跨版本 / 部分表:mysqldump。
- 大库 / 生产热备 / 快速恢复:XtraBackup。
- 误删回滚 / 定点恢复:全量备份 + binlog PITR。
- 防误删兜底:延迟从库 + 异地备份。
- 备份有效性的唯一证明:定期恢复演练。
把备份当作一项持续运营的工作,而不是一次性的脚本任务,才能在真正出事时把“删库跑路”变成“有惊无险”。











