WHERE 忘写了的那个下午
运维同事在从库清历史数据,DELETE FROM orders_log——条件忘带了,4000 万行日志表瞬间清空。幸好:从库(super_read_only 前的老账)误删,主库数据还在;但如果主库被误删呢?备份不是把数据拷走,是把「恢复的能力」保存下来——没演练过恢复的备份,等于没备份。这篇先讲清备份工具,再完整推演一次误删恢复。
两大门派:逻辑备份与物理备份
| 维度 | mysqldump(逻辑) | XtraBackup(物理) |
|---|---|---|
| 产物 | SQL 文本,可读可改可跨版本 | 数据文件拷贝,只能同版本恢复 |
| 速度 | 慢,大表导数小时起 | 快,文件级拷贝 |
| 恢复 | 重放 SQL,更慢 | 拷回 + prepare,快 |
| 适用 | 中小库、单表导出、跨库迁移 | T 级大库、全量常规备份 |
InnoDB 场景的一致性来自 MVCC:mysqldump 加 --single-transaction 开启一个长事务,靠第 8 篇的快照读拿到「备份开始那一刻」的一致视图,全程不锁表;XtraBackup 则直接拷数据文件并追 redo,靠崩溃恢复机制保证一致——底层又回到第 7 篇的两本日志。
# 逻辑备份:单事务一致性 + 记录 binlog 位点
mysqldump --single-transaction --source-data=2 --triggers --routines --all-databases > full.sql
# 物理备份(XtraBackup 8.0):全量
xtrabackup --backup --target-dir=/data/backup/full --user=backup --password=***
xtrabackup --prepare --target-dir=/data/backup/full8.0 也可以用 MySQL 自带的克隆插件或 MySQL Shell 的 dump 工具(并行、压缩、断点续传),思路相同:一致性快照 + 位点记录。
时间点恢复:全量 + binlog 的接力
全量备份是快照,备份之后的数据靠 binlog 补——这就是第 10 篇说 binlog 是「数据恢复」用途的兑现。误删恢复的标准流程:
- 第一步:恢复最近一次全量备份(先把当前现场另存一份,别二次破坏);
- 第二步:用 mysqlbinlog 重放全量备份点到误删前一刻的 binlog;
- 第三步:跳过误删语句,继续重放到最新(业务流量保持熔断或走从库)。
# 提取某时间段的 binlog 为 SQL,先人工确认再重放
mysqlbinlog --start-datetime="2026-09-14 14:00:00" --stop-datetime="2026-09-14 15:29:59" mysql-bin.000123 > replay.sql起止时间按「全量备份完成时刻」到「误删发生前一刻」取值。GTID 模式下(第 11 篇)更省心:恢复全量后 START REPLICA 指向存有全量之后 binlog 的实例即可自动补齐。
误删演练复盘
把开头的事故按流程走一遍:orders_log 在从库被清空 → 恢复最近全量到临时实例 → mysqlbinlog 重放至误删前 1 秒 → 导出 orders_log 数据灌回 → 校验行数与抽样内容 → 全程 40 分钟。事后加固三件套:高危 SQL 二次确认(客户端开启 safe-updates)、删除一律先 SELECT 核对再执行、权限最小化(业务账号不给 DROP/TRUNCATE)。
备份策略清单
- 全量(XtraBackup 每日)+ binlog 实时留存,RPO 可到秒级;
- 备份必须异地(另一机房/对象存储),防整盘灾难;
- 定期恢复演练(至少季度级),备份文件校验 md5 不等于能恢复;
- 延迟从库(REPLICA 延迟 1 小时)是误删的最后防线——误删后还能从延迟从库抢救数据;
- 主从不是备份:误删会被复制到所有从库(本文开头幸运在于是从库被删,若主库被删,主从一起没)。
安全题答完,22 篇全部到齐。下一篇收官复盘:把整个系列收进一张作战地图。
咖啡凉了,记得趁热喝。
评论 (0)