MySQL进阶篇之备份(下半篇)

一、备份的基本概念与分类

1.1 为什么要备份

备份是数据安全的最后一道防线,用于应对:误删除/误更新(DML 误操作、DROP TABLE)、硬件故障、软件 Bug、机房灾难、数据被恶意篡改等。衡量备份方案的两个核心指标:

  • RPO(恢复点目标):最多能容忍丢失多少数据(比如丢 5 分钟、丢 1 小时);
  • RTO(恢复时间目标):最多能容忍多长时间恢复服务。

1.2 备份的三个正交分类维度

分类维度 类型 区分依据
按备份内容/方式 逻辑备份 vs 物理备份 备份的是 SQL 文本还是原始数据文件
按备份范围 全量 vs 增量 vs 差异 备份哪些数据
按备份时数据库状态 热备 vs 温备 vs 冷备 备份期间数据库能否对外读写

1.3 逻辑备份 vs 物理备份

逻辑备份 :导出数据库的结构和数据,表现为 SQL 语句(CREATE/INSERT)或分隔文本(CSV)。代表工具 mysqldump。

  • 优点:文件是纯文本,可读、可编辑、跨平台/跨版本兼容性好、可只恢复单个库或单表;
  • 缺点:备份和恢复都要经过 SQL 层(导出是查询、导入是逐行执行 INSERT),大数据量下很慢。

物理备份 :直接拷贝数据库在磁盘上的原始文件(数据文件、日志文件、配置文件等)。代表工具 XtraBackup、文件系统快照(LVM、云盘快照)。

  • 优点:文件拷贝级别的速度,备份恢复都很快,适合大数据量;
  • 缺点:文件与 MySQL 版本、操作系统、配置绑定,可移植性差,不能直接查看其中某条数据,通常按整个实例恢复。

1.4 全量、增量、差异备份

  • 全量备份(Full) :备份某一时刻数据库的全部数据;
  • 增量备份(Incremental):以上一次备份(全量或上一次增量)为基准,只备份之后变化的数据;
  • 差异备份(Differential) :以最近一次全量备份为基准,备份全量之后所有变化的数据。
类型 每次备份量 恢复时需要 恢复速度
增量 小(只备最近变化) 全量 + 依次回放所有增量(依赖链) 慢
差异 越来越大(累积全量后的变化) 全量 + 最近一次差异(只需两个副本) 快

XtraBackup 原生支持的是增量备份(靠 LSN 对比)。

1.5 热备、温备、冷备

  • 热备(Hot) :数据库正常运行,读写都不受影响 地完成备份。InnoDB 下用 mysqldump --single-transaction 或 XtraBackup 可实现;
  • 温备(Warm) :数据库运行但被置为只读或加锁,能查不能写(如对 MyISAM 表锁表导出);
  • 冷备(Cold) :先停掉 mysqld,再直接拷贝文件,最简单且数据一定一致,但期间服务中断。

1.6 物理热备为什么必须配合 redo log(WAL 原理)

InnoDB 采用 WAL(Write-Ahead Logging,预写日志) :事务提交时先把 redo log 刷盘,再异步把内存中的脏页刷到数据文件 。因此正常运行时,磁盘上的数据文件内容可能落后于内存和 redo log。

这带来一个关键结论:

  • 冷备直接拷数据文件即可(停机后所有数据已落盘,是一致的);
  • 热备在服务运行中直接拷贝数据文件是不行的------拷贝持续一段时间,期间文件在不断变化,且部分最新数据还在内存里,拷出来的文件处于"撕裂"的不一致状态。

所以物理热备的正确做法是:拷贝数据文件的同时,持续记录这段时间产生的 redo log,最后回放 redo log 把备份推到一个一致状态(这正是 XtraBackup 做的事,见第四章)。


二、mysqldump 逻辑备份

2.1 原理与特点

mysqldump 通过查询数据库,把库表结构和数据导出为一组 SQL 语句(DROP/CREATE/INSERT),执行这些 SQL 即可重建数据。兼容性好、跨平台、易恢复,但单线程、逐行处理,大数据量慢,一般适合 10G 以下的备份。

2.2 基本语法

复制代码
# 导出(用 mysqldump,重定向到文件)
mysqldump [options] > dump.sql

# 导入(用 mysql 客户端,不是 mysqldump!)
mysql [options] < dump.sql

2.3 常用选项

选项 作用
--all-databases,-A 备份所有数据库
--databases db1 db2,-B 备份指定多个库(会带 CREATE DATABASE)
--tables t1 t2 备份指定表(须放在最后,其后名称都视为表名)
--no-data,-d 只导出表结构,不导出数据
--no-create-info,-t 只导出数据,不生成 CREATE TABLE
--no-create-db,-n 不生成 CREATE DATABASE
--extended-insert,-e 用一条多值 INSERT 插入多行(默认开启,减小文件、加快导入)
--add-drop-table 每个 CREATE TABLE 前加 DROP TABLE IF EXISTS(默认开启)
--add-drop-database 每个 CREATE DATABASE 前加 DROP DATABASE
--add-locks 每张表用 LOCK TABLES / UNLOCK TABLES 包裹(默认开启,加快导入)
--lock-tables,-l 导出前锁定当前库的所有表(只读锁,适合 MyISAM)
--lock-all-tables,-x 导出期间锁定所有库的所有表(全局读锁)
--single-transaction InnoDB 一致性热备(不锁表,见 2.4)
--source-data[=1/2] 记录 binlog 位点(8.0;5.7 叫 --master-data,见 2.5)
--flush-logs,-F 开始导出前切换 binlog,便于增量恢复定位起点
--routines,-R 导出存储过程和函数
--triggers 导出触发器(默认开启,--skip-triggers 关闭)
--events,-E 导出事件调度器
--ignore-table=db.table 跳过指定表(可多次使用)
--no-tablespaces 不处理表空间,避免导出时需要 PROCESS 权限
--set-gtid-purged=off GTID 环境下普通恢复/迁移时使用,避免导入时写 gtid_purged 报错
--force,-f 导出中遇到 SQL 错误也继续
--no-autocommit 每张表的导入包在 SET autocommit=0; ... COMMIT; 之间,加快导入
--default-character-set=utf8mb4 指定字符集,避免中文乱码

2.4 一致性热备:--single-transaction(重点)

默认导出过程中数据还在被修改,会产生三类不一致:

  1. 备份到未提交事务写入的数据(事务后来回滚了,备份却留下了脏数据);
  2. 备份期间发生回滚,导致备份中包含已被删除/修改的数据;
  3. 备份期间新插入的数据,部分表导到、部分表没导到,跨表不一致。

--single-transaction 的原理(仅对 InnoDB 等事务引擎有效):

  1. 短暂执行 FLUSH TABLES WITH READ LOCK 加全局读锁;
  2. 开启 RR 隔离级别的事务并建立一致性快照:START TRANSACTION WITH CONSISTENT SNAPSHOT;
  3. 若同时用了 --source-data,在锁内读取当前 binlog 位点;
  4. 释放全局读锁;
  5. 之后全程基于 MVCC 快照逐表导出,快照建立时刻的数据被固定,不阻塞其他事务写入。

注意:它只对 InnoDB 有效;MyISAM 不支持事务,导出 MyISAM 表仍必须锁表(温备)。

2.5 --source-data 与 binlog 位点

  • --source-data=2 :在 dump 文件中以注释 形式写入 CHANGE REPLICATION SOURCE TO SOURCE_LOG_FILE='binlog.xxx', SOURCE_LOG_POS=位点,记录备份对应的 binlog 位置;
  • =1:该语句不注释、会生效(用于搭建从库)。

这个位点是"全量备份 + binlog 时间点恢复"的衔接点(见第五章)。

2.6 使用样例与文件头解读

复制代码
mysqldump -ubackup_user -p -h127.0.0.1 -P3306 \
  -B testdb --default-character-set=utf8mb4 \
  --single-transaction --source-data=2 \
  --triggers --events --routines \
  --set-gtid-purged=off > /backup/mysql/$(date +%Y%m%d)_0.sql

dump 文件开头的一串 SET 是为了导入时又快又安全:临时关闭外键检查、唯一性检查、设置字符集和时区等,导入结束后恢复原值:

复制代码
/*!50503 SET NAMES utf8mb4 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;

2.7 恢复方式

复制代码
# 方式1:命令行重定向(最常用)
mysql -uroot -p < /backup/mysql/xxx.sql

# 方式2:进入 MySQL 后用 source
mysql> source /backup/mysql/xxx.sql;
mysql> \. /backup/mysql/xxx.sql;

# 方式3:管道流式迁移(一台机器导出,直接导入另一台,不落盘)
mysqldump -ubackup_user -p -h127.0.0.1 -B testdb \
  --single-transaction --source-data=2 \
  --triggers --events --routines --set-gtid-purged=off \
  | mysql -uroot -p -h192.168.100.237 -P3306

用 pv 查看导入进度(安装命令是 apt install pv):

复制代码
# 显示进度条;-L 用于限速(字节/秒,如 -L 10M)
pv /backup/mysql/dump.sql | mysql -uroot -p -h127.0.0.1 -P3306

2.8 权限与注意事项

  • 导出表需 SELECT 权限;导出视图需 SHOW VIEW ;导出触发器需 TRIGGER;
  • 未用 --single-transaction 时需 LOCK TABLES ;未用 --no-tablespaces 时需 PROCESS;
  • 默认不备份 INFORMATION_SCHEMA、performance_schema、sys,需要时显式指定;
  • mysqldump 是单线程,大数据量耗时长;对 MyISAM 会长时间锁表影响业务;
  • 恢复时间通常是备份时间的数倍(要逐条执行 INSERT、建索引),故大数据量应改用物理备份。

三、SELECT INTO OUTFILE / LOAD DATA / mysqlimport 备份

这是比 INSERT 更快的文本数据导入导出方式(制表符/CSV 分隔的纯数据,适合简单数据迁移和大批量导入)。

复制代码
-- 导出:查询结果写到服务器端文件(注意:文件不能已存在,防止覆盖)
SELECT * FROM student INTO OUTFILE '/var/lib/mysql-files/student.txt'
  FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';

-- 导入:把服务器端文件数据装入表
LOAD DATA INFILE '/var/lib/mysql-files/student.txt'
  INTO TABLE student
  FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';

要点:

  1. 文件位置由服务端变量 secure_file_priv 限制(NULL 表示禁用,指定目录表示只能在该目录读写,空表示不限制);INTO OUTFILE 生成的是服务器端文件,需要 FILE 权限;
  2. LOAD DATA INFILE 读服务器端 文件;加 LOCAL 关键字(LOAD DATA LOCAL INFILE)读客户端 文件并上传;
    1. mysqlimport 是 LOAD DATA INFILE 的命令行封装:

      复制代码
      mysqlimport -uroot -p [--local] dbname student.txt

      它靠文件名确定表名:去掉扩展名后的文件名必须等于目标表名(student.txt → student 表)。


四、XtraBackup 物理热备

4.1 工具与原理

Percona XtraBackup 是 Percona 开源、免费的 MySQL 物理热备工具(8.0 版本对应 MySQL 8.0,2.4 对应 5.7)。它对 InnoDB 表可以真正热备、不阻塞读写,支持全量和增量备份。

热备原理(对应 1.6 节):

  1. 后台线程拷贝数据文件(此时数据库正常运行);
  2. 拷贝期间持续记录新产生的 redo log(存为 xtrabackup_logfile);
  3. 数据文件拷贝完成后,得到的是不一致副本;
  4. 恢复前执行 --prepare,回放 redo log(前滚已提交事务)、回滚未提交事务,让备份达到一致性状态。

4.2 全量备份

复制代码
xtrabackup --defaults-file=/etc/mysql/my.cnf \
  --host=localhost --port=3306 --user=backup_user --password=123456 \
  --use-memory=1G --parallel=2 \
  --backup --target-dir=/backup/mysql/full
参数 作用
--defaults-file 配置文件路径(必须放在第一位),用于确定 datadir 等
--use-memory=1G prepare 阶段可用的内存(主要在准备阶段提速)
--parallel=2 并行拷贝/恢复的线程数
--backup 表示执行备份
--target-dir 备份输出目录

4.3 备份目录中的关键文件

  • xtrabackup_binlog_info:备份完成时的 binlog 文件名、position(和 GTID),用于 PITR/搭从库;
  • xtrabackup_checkpoints :备份类型和 LSN 信息(from_lsn、to_lsn、last_lsn),增量备份就靠 LSN 对比;
  • xtrabackup_info:备份的元信息(版本、时间、引擎、GTID 等);
  • xtrabackup_logfile:备份期间累积的 redo log。

4.4 恢复流程(prepare → copy-back)

复制代码
# 1)停止 mysqld,清空(或移走)旧的 datadir,再建同名空目录
systemctl stop mysqld
rm -rf /var/lib/mysql/*
mkdir -p /var/lib/mysql

# 2)prepare:回放/回滚日志,把备份推到一致性状态(可加大 --use-memory)
xtrabackup --prepare --use-memory=1G --target-dir=/backup/mysql/full

# 3)copy-back:把准备好的文件拷回 datadir
xtrabackup --defaults-file=/etc/mysql/my.cnf \
  --copy-back --parallel=2 --target-dir=/backup/mysql/full

# 4)修正属主(手工新建的目录属主是 root,mysqld 无法读写)
chown -R mysql:mysql /var/lib/mysql

# 5)启动
systemctl start mysqld

注意:--prepare 后的数据才是一致可用的;--copy-back 要求 datadir 为空(除非用 --force-non-empty-directories)。也可以用 --move-back 直接移动而非复制。

4.5 增量备份(简述)

复制代码
# 全量
xtrabackup --backup --target-dir=/backup/mysql/full ...
# 第一次增量(基于全量)
xtrabackup --backup --target-dir=/backup/mysql/inc1 \
  --incremental-basedir=/backup/mysql/full ...
# 第二次增量(基于第一次增量)
xtrabackup --backup --target-dir=/backup/mysql/inc2 \
  --incremental-basedir=/backup/mysql/inc1 ...

# 准备全量恢复
xtrabackup --prepare --apply-log-only --target-dir=/backup/mysql/full
# 准备第⼀次增量恢复
xtrabackup --prepare --apply-log-only --target-dir=/backup/mysql/full \
--incremental-dir=/backup/mysql/inc1
# 准备第⼆次增量恢复
xtrabackup --prepare --apply-log-only --target-dir=/backup/mysql/full \
--incremental-dir=/backup/mysql/inc2
......
# 最后一次增量恢复
xtrabackup --prepare --target-dir=/backup/mysql/full \
--incremental-dir=/backup/mysql/incn

恢复时要按顺序合并:先 prepare 全量(加 --apply-log-only 保持可继续合并),再依次合并各增量(最后一个增量不加 --apply-log-only 以便回滚未提交事务),最后再 copy-back。


五、全量备份 + binlog 时间点恢复(PITR)

全量备份只能恢复到"备份那一刻",要恢复到备份之后、故障之前的任意时间点,必须配合上一篇讲的 binlog:

复制代码
时间轴:  全量备份点 ────────────────▶ 误操作发生
              │                          │
              │ ① 恢复全量备份            │
              │ ② 从备份位点开始重放 binlog,停在误操作前
              ▼
         恢复到任意时间点

操作步骤:

  1. 全量备份时记录 binlog 位点(mysqldump 的 --source-data=2,或 XtraBackup 的 xtrabackup_binlog_info);

  2. 故障后先恢复全量备份;

  3. 用 mysqlbinlog 从该位点开始,按位置或时间截取并重放 binlog,跳过误操作:

    mysqlbinlog --start-position=位点 --stop-position=误操作前位点
    /var/lib/mysql/binlog.0000xx | mysql -uroot -p

这就是"定期全量 + 持续 binlog"的经典备份策略:全量备份提供基线,binlog 负责把数据前滚到任意时间点,RPO 可低至接近 0。


六、三种备份手段对比

维度 mysqldump SELECT INTO OUTFILE / LOAD XtraBackup
类型 逻辑备份(SQL 文本) 逻辑备份(分隔文本) 物理备份(数据文件+redo)
备份方式 单线程逐表查询 单表数据导出 多线程文件拷贝
大数据量速度 慢(10G 以下) 快(仅数据) 很快
热备 InnoDB 加 --single-transaction 可热备 运行中可用 InnoDB 真热备
恢复方式 执行 SQL(慢) LOAD 装入单表 拷回文件(快)
粒度/可读性 可单库单表、文本可读 单表纯数据、可读 整实例、不可读、移植性差
典型场景 小库、迁移、逻辑快照 大批量数据导入导出 大库生产备份、增量备份

七、核心总结

  1. 备份分三个正交维度:逻辑/物理(备份什么)、全量/增量/差异(备份范围)、热/温/冷(备份时数据库状态)。
  2. 增量 以上一次备份为基准、恢复需全量+所有增量;差异以最近全量为基准、恢复只需全量+最近差异。
  3. InnoDB 是 WAL(先写 redo log 再刷脏页);冷备直接拷文件,**物理热备必须"拷数据文件 + 记录并回放 redo log"**才能保证一致。
  4. mysqldump 导出用 mysqldump >、导入用 mysql < ;--single-transaction 靠 RR 一致性快照实现 InnoDB 不锁表热备;--source-data=2 记录 binlog 位点;--extended-insert 是多值 INSERT。
  5. mysqldump 单线程、恢复慢,适合小库;INTO OUTFILE/LOAD DATA 是更快的纯文本导入导出,文件在服务器端受 secure_file_priv 限制,mysqlimport 靠文件名确定表名。
  6. XtraBackup 是开源物理热备工具 :--backup 备份 → --prepare 回放 redo log 得到一致副本 → --copy-back 拷回 datadir → chown -R mysql:mysql 后启动;增量备份靠 LSN。
  7. 生产标准策略是"定期全量(物理或逻辑)+ 持续 binlog ",用全量做基线、binlog 做时间点恢复(PITR),并根据 RPO/RTO 设计频率,且要定期做恢复演练(能恢复的备份才算备份)。
相关推荐
计算机就业还在扩大1 小时前
Redis中的setnx是原子性的?
数据库·redis·缓存
updayday8541 小时前
供应商补交资质文件时,采购难以核对缺件和新版本 - Ping64 文件收集
大数据·网络·数据库·安全·智能路由器
PaperData1 小时前
2012-2025年省市区县政府周边的夜间灯光亮度及是否加班数据
数据库
Light602 小时前
四款云端 Agent 的安全边界画在三个地方
大数据·数据库·安全·个人agent·安全边界·提示注入·grok bot
IvorySQL2 小时前
PostgreSQL 日报| pg_vectorsearch 开源向量搜索发布(10 月 14 日)
数据库·人工智能·postgresql·开源·区块链
m0_587383002 小时前
碰碰好评卡功能落地全流程实战指南 附核心逻辑与常见问题解决方案
java·前端·数据库·后端·struts·需求分析
Y3815326622 小时前
SerpBase + RAG 实战:用搜索 API 给知识库接上实时数据,回答不再过期
java·服务器·数据库
骑着蜗牛撵大象3272 小时前
SQL 编辑器不是高级记事本:KStudio 与 KSQL Developer 里的建表与增删改查手法
数据库·sql·mysql·编辑器·crud·执行计划
Access开发易登软件2 小时前
我全新开发了一套 Access 通用 Excel 导入工具,现在开源了
数据库·microsoft·excel·mfc·vba·access·access开发