MySQL十五个备份恢复方法是什么

文章导读
「十五个」并不是 MySQL 官方给出的编号清单,官方文档里没有这一条。排查时说的这句话,通常指把逻辑导出、物理拷贝、快照、binlog 增量、复制、Clone 插件、表空间传输这些手段按场景摊开清点一遍,再判断当前这套库能用哪几种、哪一种的产物真的能在目标实例上恢复出来。因此第一步不是选方法,而是先确认工具和日志到底在不在。
📋 目录
  1. A MySQL十五个备份恢复方法有哪些
  2. B MySQL十五个备份恢复:先把能核对的事实摆清楚
  3. C MySQL十五个备份恢复最容易搞错的一点
  4. D MySQL十五个备份恢复:一个照着就能做完的做法
  5. E MySQL十五个备份恢复:怎么验证结果对不对
A A

「十五个」并不是 MySQL 官方给出的编号清单,官方文档里没有这一条。排查时说的这句话,通常指把逻辑导出、物理拷贝、快照、binlog 增量、复制、Clone 插件、表空间传输这些手段按场景摊开清点一遍,再判断当前这套库能用哪几种、哪一种的产物真的能在目标实例上恢复出来。因此第一步不是选方法,而是先确认工具和日志到底在不在。

先盘点可用手段,再谈选型:用 mysqldump --version、xtrabackup --version、SHOW PLUGINS、SHOW BINARY LOGS 确认工具与日志位置;按“能否恢复到指定时间点”和“是否需要停机”两类归档;最后在独立实例上真恢复一次。有备份文件不等于能恢复,版本、页大小、字符集不一致时物理备份最容易失败。

MySQL十五个备份恢复方法有哪些

这一步在「MySQL十五个备份恢复」流程里对应“盘点可用手段”,位置在选型和演练之前。确认是不是这一项,看产物形态而不是名字:文本 .sql 或 .tsv 属于逻辑备份;目录里带 ibdata1、xtrabackup_checkpoints 属于物理备份;控制台上的快照 ID 属于存储层备份。三者恢复方式完全不同,混为一谈是最初的分歧来源。

按产物形态摊开,常见做法可以这样列,每一条都能用命令或目录核对到:

  1. mysqldump 整库逻辑导出,产物 .sql,核对 mysqldump --version。
  2. mysqlpump 并行导出,8.0 已移除,核对命令是否还存在。
  3. mydumper / myloader 并行备份与恢复,核对 mydumper --version。
  4. SELECT ... INTO OUTFILE 配合 LOAD DATA,按表做文本交换。
  5. 停库冷备,直接拷 datadir,位置来自 SELECT @@datadir;。
  6. LVM、ZFS 或云盘快照,核对 lvs 或控制台快照列表。
  7. XtraBackup 全量,核对 xtrabackup --version。
  8. XtraBackup 增量,核对 xtrabackup_checkpoints 里的 incremental 字段。
  9. MySQL Enterprise Backup,仅商业版,核对 mysqlbackup --version。
  10. binlog 增量与时间点恢复,核对 SHOW BINARY LOGS;。
  11. 主从复制或延迟从库,核对 SHOW REPLICA STATUS; 里的 Source_Host 与 SQL_Delay。
  12. Clone Plugin 本地或远程克隆,核对 SHOW PLUGINS; 里有没有 clone。
  13. 可传输表空间,FLUSH TABLES ... FOR EXPORT 加 .ibd 与 .cfg 拷贝。
  14. CSV 导出做数据交换,产物可用 head -1 看到表头。
  15. 对象存储归档加恢复脚本,核对备份目录与对象 key 是否对得上。

能对上三到四种常用手段、并且知道各自产物在哪个目录,这一步就算做完;凑不满十五种不影响判断,硬凑反而会把冷备和快照当成两件事重复计数。

MySQL十五个备份恢复:先把能核对的事实摆清楚

先把对象和前提写清楚:要恢复的是哪个实例、哪个库、多大体积、允许停多久、能丢多少数据。这些不靠猜,下面的命令能直接读到。

mysql -uroot -p -e "SELECT @@version, @@version_comment, @@innodb_page_size, @@character_set_server, @@log_bin, @@binlog_format;"
mysql -uroot -p -e "SELECT @@binlog_expire_logs_seconds;"
mysql -uroot -p -e "SHOW BINARY LOGS;"
mysql -uroot -p -e "SHOW PLUGINS;"
mysql -uroot -p -e "SHOW GRANTS FOR CURRENT_USER();"
df -h /var/lib/mysql /backup

5.7 上没有 binlog_expire_logs_seconds,换成 SELECT @@expire_logs_days;。备份侧同样只记录看得见的东西:ls -lh /backup 看产物体积和修改时间,head -30 app_full.sql 看文件头有没有位点注释,形如 -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000012', MASTER_LOG_POS=1234;,有没有这一行决定了能不能做时间点恢复。物理备份则看备份目录下有没有 xtrabackup_info 和 xtrabackup_checkpoints。

判断顺序建议按这个次序走,前面的不成立后面的结论就不作数:

  1. 版本与 innodb_page_size,决定物理备份能不能直挂。
  2. 表清单与存储引擎,决定一致性快照是否成立。
  3. log_bin 是否开启、binlog 保留期,决定能不能做到时间点。
  4. 备份产物是否带位点注释,决定增量从哪里接。
  5. 目标实例磁盘空间与停机窗口,决定恢复方式选在线还是离线。

这一段先不下结论,只把这些值抄在一张表里,选方法时才有依据。权限也属于事实项:逻辑备份至少要 SELECT、SHOW VIEW、TRIGGER、EVENT、LOCK TABLES、RELOAD、REPLICATION CLIENT,缺 REPLICATION CLIENT 时位点注释会缺失,很多人是到恢复时才发现。

MySQL十五个备份恢复方法是什么

MySQL十五个备份恢复最容易搞错的一点

最常见的误解是把备份任务的成功日志当成“这份备份能恢复”。任务跑完只说明导出动作没报错,不说明产物能在目标实例上打开。分界在版本、页大小、redo 日志大小这几个参数是否与目标实例一致,物理备份尤其如此。

能区分两种情况的动作是:读备份集里的元信息,和当前实例参数逐项比。

cat /backup/xtra_20250101/xtrabackup_info | grep -E 'server_version|innodb_page_size|innodb_log_file_size'
mysql -uroot -p -e "SELECT @@version, @@innodb_page_size, @@innodb_log_file_size;"

两边一致,物理备份可以 prepare 后 copy-back;不一致,就不要往生产 datadir 上拷,改走逻辑导入,或者先在同版本空实例上恢复再升级。

另一条容易混的是非事务表:库里有 MyISAM 表时,--single-transaction 拿到的并不是全局一致快照。用下面这句能立刻判断:

SELECT table_schema, table_name, engine FROM information_schema.tables
WHERE table_schema NOT IN ('mysql','sys','performance_schema','information_schema') AND engine <> 'InnoDB';

有返回行,这类表要安排在写入静默窗口,或改用加锁方式备份;没有返回行,--single-transaction 的一致性才谈得上成立。

MySQL十五个备份恢复:一个照着就能做完的做法

给一条通用路径:逻辑全备加 binlog 增量,恢复到指定时间点。它不要求停机,适合中小体量和需要精确到秒的场景;大体量换成 XtraBackup,思路一致,只是全备那一步换物理备份。

第一步做全备并记录位点。8.0.26 及以上用 --source-data=2,更早版本换成 --master-data=2:

mysqldump -uroot -p --single-transaction --quick --routines --triggers --events --source-data=2 --set-gtid-purged=OFF --default-character-set=utf8mb4 --databases app > /backup/app_$(date +%F_%H%M).sql

执行完应看到文件非空,文件头有被注释掉的位点行。第二步把 binlog 一并留档:

MySQL十五个备份恢复方法是什么
mysqlbinlog --read-from-remote-server --host=127.0.0.1 --user=backup --raw --result-file=/backup/binlog/ mysql-bin.000012 mysql-bin.000013

第三步恢复全备,目标实例先建空库再导入:

mysql -uroot -p -e "CREATE DATABASE IF NOT EXISTS app DEFAULT CHARACTER SET utf8mb4;"
grep -m1 -E 'CHANGE MASTER|CHANGE REPLICATION' /backup/app_*.sql
mysql -uroot -p app < /backup/app_2025-01-01_0300.sql

导入过程中不该出现 ERROR 1062 之类的报错,结束后表数量应与备份时一致。第四步从位点重放 binlog:

mysqlbinlog --start-position=1234 --stop-datetime='2025-01-01 10:30:00' --database=app /backup/binlog/mysql-bin.000012 | mysql -uroot -p app

--stop-datetime 通常要往前留几秒,避免把误操作那条语句重放进来;跨多个 binlog 时按序号依次重放,不要跳号。物理备份的对照做法是先 xtrabackup --backup --target-dir=/backup/xtra,再 xtrabackup --prepare --target-dir=/backup/xtra,最后 xtrabackup --copy-back --target-dir=/backup/xtra,copy-back 之后把 datadir 属主改回 mysql 再启动。

MySQL十五个备份恢复:怎么验证结果对不对

恢复完不要只看“命令没报错”。按结构、行数、内容、时间点四层验:

mysql -uroot -p -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='app';"
mysql -uroot -p -e "SELECT COUNT(*) FROM app.orders;"
mysql -uroot -p -e "CHECKSUM TABLE app.orders;"
mysqlcheck -uroot -p --databases app

正常结果长这样:表数量与备份前一致;抽查的核心表行数对得上;mysqlcheck 每张表输出 OK;CHECKSUM TABLE 在源库和恢复库两侧拿到相同值,大表执行有成本,建议只挑关键表。

时间点是否正确,用一条可辨认的记录验最稳妥:在测试库先插一条标记行并记下时间,从该时间之前恢复,恢复后这条标记行不存在,说明停止位点生效。如果这套库还有从库,SHOW REPLICA STATUS; 里 Last_Error 为空、Seconds_Behind_Source 在回落,才算接上。

风险边界也写清楚:以上验证只能证明这份备份在这台目标实例上可用,不能证明下一次备份也可用。定期在独立实例上重跑一遍恢复,比反复检查备份日志更有意义。