Oamc

MySQL 备份与恢复

本页目录

场景

定期备份数据库,出事了能恢复到某个时间点。

前置条件

  • 备份盘容量够,最好和数据库不在同一块盘
  • 知道恢复的 RPO:能接受丢多久的数据
  • 大库(上百 G)用物理备份,小库用逻辑备份

配置

逻辑备份(mysqldump,几十 G 以内)

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,大库)

xtrabackup --backup --user=root --password=*** \
  --target-dir=/backup/xtra/$(date +%F)

xtrabackup --prepare --target-dir=/backup/xtra/$(date +%F)

恢复

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

验证

mysql -u root -p -e "SELECT COUNT(*) FROM appdb.orders;"
mysql -u root -p -e "SHOW TABLE STATUS FROM appdb;"

恢复完对一下关键表的行数和最新时间戳。

回滚

恢复前先备份当前状态,恢复错了还能退回去:

mv /var/lib/mysql /var/lib/mysql.broken

坑

  • --single-transaction 只对 InnoDB 有效,有 MyISAM 表会锁表。
  • 不加 --databases 时导出的文件里没有 CREATE DATABASE,恢复要先建库。
  • 乱码问题九成是导出/导入两端字符集不一致。
  • xtrabackup --prepare 不能省,跳过去启不来。
  • 备份文件不验证等于没有,定期拿一份真恢复一次。
  • 主从环境恢复要处理 GTID,否则复制起不来。