0aa8fe6
这次没有正文改动。
这是 database/MySQL 备份与恢复.md 的改动记录。后台每次保存都会留一份快照,
这里显示的是快照之间的差异,不会混入其他文章的改动。
还没有后台修改记录。
下面是 Git 里的提交,可能包含其他文章的改动(因为一次提交会带上工作区所有变化)。
0aa8fe6
这次没有正文改动。
a0b4968
@@ -0,0 +1,76 @@ +--- +tags: [MySQL, 备份, 恢复] +order: 20 +--- + +# MySQL 备份与恢复 + +## 场景 + +定期备份数据库,出事了能恢复到某个时间点。 + +## 前置条件 + +- 备份盘容量够,最好和数据库不在同一块盘 +- 知道恢复的 RPO:能接受丢多久的数据 +- 大库(上百 G)用物理备份,小库用逻辑备份 + +## 配置 + +### 逻辑备份(mysqldump,几十 G 以内) + +```bash +mysqldump -u root -p \ + --single-transaction --routines --triggers --events \ + --default-character-set=utf8mb4 \ + --databases appdb > /backup/appdb_$(date +%F).sql + +gzip -9 /backup/appdb_$(date +%F).sql +``` + +### 物理备份(Percona XtraBackup,大库) + +```bash +xtrabackup --backup --user=root --password=*** \ + --target-dir=/backup/xtra/$(date +%F) + +xtrabackup --prepare --target-dir=/backup/xtra/$(date +%F) +``` + +### 恢复 + +```bash +systemctl stop mysqld +# 逻辑 +mysql -u root -p appdb < /backup/appdb.sql +# 物理 +xtrabackup --copy-back --target-dir=/backup/xtra/2026-10-18 +chown -R mysql:mysql /var/lib/mysql +systemctl start mysqld +``` + +## 验证 + +```bash +mysql -u root -p -e "SELECT COUNT(*) FROM appdb.orders;" +mysql -u root -p -e "SHOW TABLE STATUS FROM appdb;" +``` + +恢复完对一下关键表的行数和最新时间戳。 + +## 回滚 + +恢复前先备份当前状态,恢复错了还能退回去: + +```bash +mv /var/lib/mysql /var/lib/mysql.broken +``` + +## 坑 + +- **`--single-transaction` 只对 InnoDB 有效**,有 MyISAM 表会锁表。 +- 不加 `--databases` 时导出的文件里没有 `CREATE DATABASE`,恢复要先建库。 +- 乱码问题九成是导出/导入两端字符集不一致。 +- `xtrabackup --prepare` 不能省,跳过去启不来。 +- 备份文件不验证等于没有,定期拿一份真恢复一次。 +- 主从环境恢复要处理 GTID,否则复制起不来。