这是 database/mysql-backup-restore.md 的每次改动内容,按时间从新到旧。其他文章一起提交的部分不会出现在这里。
#1
2026-10-18
+76
−0
docs: 新增数据库/虚拟化/监控/备份 4 个分类和 13 篇文章
a0b4968
new file mode 100644
@@ -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,否则复制起不来。