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,否则复制起不来。