一、数据库备份基础分类
1. 按数据库服务运行状态划分备份方式
- 冷备份 :备份时停止数据库服务,将整个数据库原始文件复制到备份设备中,业务暂停。
- 热备份 :备份全程数据库处于运行状态,业务读写不受影响,适用于生产环境。
2. 按备份的数据形式划分备份方式
- 物理备份 :备份数据库服务器磁盘上存储的原始数据文件,可直接拷贝恢复;优点是恢复速度快,缺点是跨平台、跨版本兼容性差。
- 逻辑备份 :备份内容为可执行的 SQL 语句,可用于不同版本、不同类型 MySQL 数据库之间的数据迁移;优点是兼容性强,缺点是备份恢复速度慢。
3. 三种常见备份策略
| 备份类型 | 备份规则 | 特点 |
|---|---|---|
| 完全备份 | 每次都进行完全备份,每次都备份所有数据 | 易于管理,备份体积大,恢复单份文件即可 |
| 差异备份 | 每周进行一次完全备份,其余每天备份 「与上一次完全备份」的差异部分 | 恢复只需全量+最后一次差异,备份体积逐渐增大 |
| 增量备份 | 其余每天备份 「与上一次备份」的差异部分 | 备份体积最小,恢复需要全量+所有增量依次合并 |
注:各备份软件对增量备份的定义不一定相同,具体定义请以实际使用的备份软件为准。

二、完全备份与恢复
2.1 冷备份(物理完全备份)
核心说明
- MySQL 默认数据目录:
/var/lib/mysql - 备份工具:
cp直接拷贝、tar打包压缩 - 注意事项:数据恢复后必须确保
mysql用户对数据目录拥有读写权限
实验环境
| 主机名 | IP地址 |
|---|---|
| mysql50 | 192.168.8.50/24 |
| mysql51 | 192.168.8.51/24 |
备份步骤可以总结为:

步骤1:mysql50 主机执行冷备份
bash
# 停止MySQL服务
[root@mysql50 ~]# systemctl stop mysqld
# 创建备份目录
[root@mysql50 ~]# mkdir /bakdir
# 方式1:直接拷贝整个数据库目录
[root@mysql50 ~]# cp -r /var/lib/mysql /bakdir/mysql.bak
# 方式2:进入数据目录,打包压缩备份
[root@mysql50 ~]# cd /var/lib/mysql
[root@mysql50 mysql]# tar -zcf /bakdir/mysql.tar.gz ./*
#补充:如果不想切入对应目录再操作,也可以这么写:
#tar -zcf /bakdir/mysql.tar.gz -C /var/lib/mysql .
# 查看备份结果
[root@mysql50 mysql]# ls /bakdir/
mysql.bak mysql.tar.gz
打压缩包的时候一定要注意仅打包内容,不要连带目录一起打包
步骤2:将备份文件传输到 mysql51
我们可以直接拷贝目录进行备份,对于较大的数据库,可以选择先压缩再拷贝
bash
# 拷贝目录备份
[root@mysql50 ~]# scp -r /bakdir/mysql.bak root@192.168.8.51:/root/
# 若数据较大,需要压缩之后再拷贝压缩包进行备份
[root@mysql50 ~]# scp /bakdir/mysql.tar.gz root@192.168.8.51:/root/
步骤3:mysql51 主机安装mysql
bash
# 安装MySQL服务
[root@mysql51 ~]# dnf -y install mysql-server mysql
# 启动服务(初始仅含默认系统库)
[root@mysql51 ~]# systemctl enable mysqld --now
使用 tar 压缩包恢复数据
直接将压缩包解压到 /var/lib/mysql/下,然后修改数据目录归属即可
bash
# 停止MySQL服务
[root@mysql51 ~]# systemctl stop mysqld
# 清空原有数据目录(模拟数据丢失)
[root@mysql51 ~]# rm -rf /var/lib/mysql/*
# 解压备份文件到数据目录
[root@mysql51 ~]# tar -xf /root/mysql.tar.gz -C /var/lib/mysql/
# 修改数据目录归属为mysql用户
[root@mysql51 ~]# chown -R mysql:mysql /var/lib/mysql
# 启动服务
[root@mysql51 ~]# systemctl start mysqld
# 登录验证数据
[root@mysql51 ~]# mysql -uroot -p'1234.com'
mysql> SHOW DATABASES;
使用 cp 拷贝目录恢复
直接将拷贝来的内容放到/var/lib/mysql/下,然后修改目录权限归属
bash
# 停止服务
[root@mysql51 ~]# systemctl stop mysqld
# 清空数据目录
[root@mysql51 ~]# rm -rf /var/lib/mysql/*
# 拷贝备份文件到数据目录
[root@mysql51 ~]# cp -r /opt/mysql.bak/* /var/lib/mysql/
# 修改权限归属
[root@mysql51 ~]# chown -R mysql:mysql /var/lib/mysql
# 启动服务并验证
[root@mysql51 ~]# systemctl start mysqld
[root@mysql51 ~]# mysql -uroot -p'1234.com'
mysql> SHOW DATABASES;
结合计划任务实现自动备份:
实际生产工作中,我们可以结合shell脚本和crontab计划任务实现定时备份
bash
systemctl start crond && systemctl enable crond # 启动并设置开机自启
systemctl status crond # 验证服务状态(显示running即为正常)
crontab -e -u root #编写计划任务
#每周四的凌晨2点执行一次这个脚本
00 02 * * 4 /root/mysqlbak.sh
#编写脚本内容:
vim /root/mysqlbak.sh
#!/bin/bash
time=$(date + "%Y%m%d")
tar -zcf /backdir/mysql${time}.tar.gz -C /var/lib/mysql .
2.2 逻辑备份(mysqldump)
核心语法
- 备份命令:
bash
mysqldump -h主机 -u用户 -p'密码' [-B 选项] > /路径/备份文件.sql
- 恢复命令:
bash
mysql -h主机 -u用户 -p'密码' < /路径/备份文件.sql
常用参数说明
-A/--all-databases:备份所有数据库-B:备份单个或多个数据库,备份文件中包含建库语句- 备份单张/多张表 :库名与表名用空格分隔,无需
-B - 注意:逻辑备份在备份与恢复操作必须在数据库服务运行状态下执行
备份操作示例(mysql50 主机)
- 备份单张表
bash
[root@mysql50 ~]# mysqldump -uroot -p'1234.com' tarena salary > /bakdir/tarena_salary.sql
注意,这里表示某个库的某个表不用:数据库名.表名来表示,用空格:数据库名 表名
- 备份多张表
bash
[root@mysql50 ~]# mysqldump -uroot -p'1234.com' tarena employees departments > /bakdir/tarena_employees_deparments.sql
- 备份单个库
bash
[root@mysql50 ~]# mysqldump -uroot -p'1234.com' -B tarena > /bakdir/tarena.sql
备份单个库的时候可以不加-B,但是备份出的sql文件中会缺少建库语句,因此在恢复数据时也需要提前创建对应库,增加了操作步骤
因此即使在备份单个库的时候,也强烈建议加上-B
- 备份多个库
bash
[root@mysql50 ~]# mysqldump -uroot -p'1234.com' -B studb db1 > /bakdir/studb_db1.sql
- 备份所有库
bash
[root@mysql50 ~]# mysqldump -uroot -p'1234.com' -A > /bakdir/allbak.sql
[root@mysql50 ~]# ls /bakdir/*.sql
传输备份文件
bash
[root@mysql50 ~]# scp /bakdir/*.sql root@192.168.8.51:/root/
整库恢复操作(mysql51 主机)
bash
# 登录数据库,删除库模拟数据丢失
[root@mysql51 ~]# mysql -uroot -p'1234.com'
mysql> DROP DATABASE tarena;
mysql> exit
# 执行恢复(-B备份的文件无需指定库名,自带建库语句)
[root@mysql51 ~]# mysql -uroot -p'1234.com' < /root/tarena.sql
# 验证恢复结果
[root@mysql51 ~]# mysql -uroot -p1234.com
mysql> use tarena;
mysql> show tables;
单表数据恢复
单表恢复时需要指定库名
bash
# 清空表数据模拟丢失
mysql> delete from salary;
mysql> exit
# 恢复单表(需指定库名)
[root@mysql51 ~]# mysql -uroot -p'1234.com' tarena < /root/tarena_salary.sql
# 验证数据行数
[root@mysql51 ~]# mysql -uroot -p'1234.com'
mysql> select count(*) from tarena.salary;
+----------+
| count(*) |
+----------+
| 8055 |
+----------+
1 row in set (0.00 sec)
2.3 冷备份与逻辑备份总结
冷备份缺点
- 跨平台、跨版本兼容性差
- 备份时间长 ,全量拷贝存在冗余,浪费存储空间
- 备份期间必须停服,业务中断
mysqldump 逻辑备份缺点
- 备份与还原效率低、速度慢
- 备份过程会锁表,数据插入和更新操作被阻塞
- 大库场景下备份文件体积大、恢复耗时长
三、增量备份与恢复(Percona XtraBackup)
3.1 Percona XtraBackup 介绍
- 一款专业的 MySQL 在线热备份工具 ,备份过程不锁库表,适合生产环境使用
- 由 Percona 组织开发,是 MySQL 分支版本的配套工具
- 支持物理级别的全量备份与增量备份,备份恢复速度远快于 mysqldump

3.2 percona安装部署
前置准备
将安装包 percona-xtrabackup-8.0.26-18-Linux-x86_64.glibc2.12-minimal.tar.gz 上传至 mysql50 和 mysql51 的 /root 目录。
注意,备份与恢复数据都需要percona,因此两个主机都要安装percona
mysql50 安装步骤
bash
# 安装依赖包
[root@host50 ~]# dnf -y install perl-DBD-MySQL
# 解压安装包
[root@host50 ~]# tar -xf percona-xtrabackup-8.0.26-18-Linux-x86_64.glibc2.12-minimal.tar.gz
# 移动并重命名目录。目录中含percona的所有操作程序
[root@host50 ~]# mv percona-xtrabackup-8.0.26-18-Linux-x86_64.glibc2.12-minimal /usr/local/percona
# 配置环境变量
[root@host50 ~]# vim /etc/bashrc
# 在文件末尾添加
export PATH=/usr/local/percona/bin:$PATH
#让系统识别 Percona 自带的数据库命令。新目录放 $PATH 前面,代表优先查找
# 刷新环境变量
[root@host50 ~]# source /etc/bashrc
# 验证命令可用
[root@host50 ~]# man xtrabackup
mysql51 安装步骤
与 mysql50 完全一致,重复上述操作即可。
bash
[root@host51 ~]# dnf -y install perl-DBD-MySQL #安装依赖包
#解压源码
[root@host51 ~ ]# tar -xf percona-xtrabackup-8.0.26-18-Linux-x86_64.glibc2.12-minimal.tar.gz
#移动并改名
[root@host51 ~ ]# mv percona-xtrabackup-8.0.26-18-Linux-x86_64.glibc2.12-minimal /usr/local/percona
#把命令添加到系统环境变量
[root@host51 ~ ]# vim /etc/bashrc
...在最后一行下方插入...
export PATH=/usr/local/percona/bin:$PATH #修改PATH变量值,添加在文件末尾
[root@host51 ~ ]# source /etc/bashrc #刷新文件
[root@host51 ~ ]# man xtrabackup #查看xtrabackup的帮助信息,按q 退出
3.3 增量备份实操(mysql50 主机)
前置规则
增量备份必须基于上一次备份进行,首次必须执行一次完全备份 。
典型策略:每周周一执行完全备份,周二到周日每天执行增量备份。
1. 周一:执行完全备份
因为该命令比较复杂,尽可能不要记命令,着重记忆步骤原理。
bash
# 这里没有写增量的选项,因此是全量备份。--target-dir指定本次全量备份文件存放目录;--datadir指定数据库目录
[root@mysql50 ~]# xtrabackup --host=127.0.0.1 --user=root --password='1234.com' --backup --target-dir=/fullbak --datadir=/var/lib/mysql
相关参数解读:
--host=127.0.0.1:指定 MySQL 服务地址,本地库写 127.0.0.1。
--user=root:数据库登录用户名。
--password='1234.com':数据库登录密码,带特殊符号 / 点号用单引号包裹避免 shell 转义
--backup:开启备份模式,代表本次操作是生成一份完整数据备份
--target-dir=/fullbak:备份输出目录,所有拷贝出来的数据库文件、redo 日志、备份信息文件都会存到 /fullbak
--datadir=/var/lib/mysql:MySQL 原始数据存放目录,也就是正在运行的数据库真实数据文件路径(ibdata1、*.ibd、系统库文件夹都在这里),xtrabackup 会读取这里的物理文件做热备
2. 周二:第一次增量备份(基于全量备份)
bash
# 插入测试新数据(充作增量数据)
mysql> insert into tarena.salary(date,employee_id,basic,bonus)values("20260610",18,25000,8000);
# 增量备份,--incremental-basedir是指定增量备份的对比目录。基准为全量备份目录/fullbak
[root@mysql50 ~]# xtrabackup --host=127.0.0.1 --user=root --password='1234.com' --backup --target-dir=/new2 --incremental-basedir=/fullbak --datadir=/var/lib/mysql
--incremental-basedir:指定基准备份目录
3. 周三:第二次增量备份(基于周二增量备份)
bash
# 插入测试新数据
mysql> insert into tarena.salary(date,employee_id,basic,bonus)values("20260710",18,25000,8000);
# 增量备份,基准为周二增量备份目录/new2
[root@mysql50 ~]# xtrabackup --host=127.0.0.1 --user=root --password='1234.com' --backup --target-dir=/new3 --incremental-basedir=/new2 --datadir=/var/lib/mysql
3.4 增量恢复实操(mysql51 主机)
恢复总步骤
- 准备恢复数据
- 依次合并所有增量备份到全量备份
- 清空目标数据库目录
- 拷贝合并后的数据到目标数据库目录
- 修改数据目录所有者为 mysql
- 重启数据库服务
步骤1:传输备份文件到 mysql51
将本机备份数据拷贝到目标主机
bash
# 拷贝全量备份
[root@mysql50 ~]# scp -r /fullbak root@192.168.8.51:/opt/
# 拷贝所有增量备份
[root@mysql50 ~]# scp -r /new* root@192.168.8.51:/opt/
步骤2:全量备份预处理
bash
[root@mysql51 ~]# xtrabackup --prepare --apply-log-only --target-dir=/opt/fullbak
--prepare作用:备份预处理阶段
--apply-log-only核心效果:只做「应用 redo 日志」,禁止回滚未提交事务
--target-dir :此处用来指定被修改、被合并的基准目录(全量目录)
步骤3:合并周二增量数据到全量备份
将周二的增量数据拷贝到周一的目录
bash
[root@mysql51 ~]# xtrabackup --prepare --apply-log-only --target-dir=/opt/fullbak --incremental-dir=/opt/new2
合并后 /opt/fullbak 包含周一全量 + 周二增量的全部数据 。
--incremental-dir=/opt/new2:指定要合并的增量数据的目录
步骤4:合并周三增量数据到全量备份
将周三的增量数据拷贝到周一的目录
bash
[root@mysql51 ~]# xtrabackup --prepare --apply-log-only --target-dir=/opt/fullbak --incremental-dir=/opt/new3
合并后 /opt/fullbak 包含周一全量 + 周二增量 + 周三增量的全部数据。
步骤5:清空原有数据目录
bash
[root@mysql51 ~]# rm -rf /var/lib/mysql/*
步骤6:拷贝备份数据到数据目录
bash
[root@mysql51 ~]# xtrabackup --copy-back --target-dir=/opt/fullbak
步骤7:修改权限并重启服务
bash
# 修改目录归属
[root@mysql51 ~]# chown -R mysql:mysql /var/lib/mysql
# 重启MySQL服务
[root@mysql51 ~]# systemctl restart mysqld
步骤8:验证数据
bash
[root@mysql51 ~]# mysql -uroot -p'1234.com'
mysql> select count(*) from tarena.salary where date=20260710;
mysql> select count(*) from tarena.salary where not date=20260710;
备份远程数据库的思路
--host 只是用来连接 MySQL 实例、获取元数据、获取 LSN、锁 MyISAM 表,不负责远程拷贝磁盘数据文件,也就是说如果数据库在别的主机,--host=远程IP 会失败。所以对应远程备份,我们有两种思路:
方案 A:登录数据库本机执行 xtrabackup(推荐)
本方法的思路是通过ssh 远程连接到数据库服务器,在数据库本机执行备份命令,再 scp 把备份文件拉回本地
bash
# 远程mysql机器上执行
xtrabackup --host=127.0.0.1 --user=root --password='1234.com' --backup --target-dir=/full --datadir=/var/lib/mysql
#通过scp拉回本机
scp /full root@本机IP:指定目录
方案 B:远程逻辑备份 mysqldump(不读物理文件)
不用 xtrabackup 物理备份,用 mysqldump 远程导出 SQL,这个支持直接填远程 host
bash
mysqldump -uroot -p'1234.com' -h192.168.8.51 -B orderdb > all.sql
导出的远程数据库的all.sql文件会直接导出在本地
四、binlog 二进制日志
实验环境
| 主机名 | IP地址 |
|---|---|
| mysql52 | 192.168.8.52/24 |
4.1 binlog 日志概述
- 又称二进制日志,是 MySQL 服务的核心日志类型之一
- 记录除查询(SELECT)之外的所有 SQL 写操作命令
- 核心用途:数据增量备份与恢复、MySQL 主从同步配置的必要条件
- 默认状态:MySQL 8.0 默认启用 binlog,默认存放路径
/var/log/mysql/binlog.*
查看当前 binlog 状态
SHOW MASTER STATUS: 作用就是查看当前主库正在写入的 binlog 文件 与日志偏移位置
sql
mysql> SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000001 | 156 | | | |
+---------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
Position 偏移量特性
- 执行写操作(建库、建表、增删改)时,Position 偏移量会增大(错误的命令不会被记录)
- 执行读操作(SELECT)时,偏移量不会发生变化
sql
-- 读操作,偏移量不变
mysql> SELECT * FROM mysql.user;
-- 写操作,偏移量更新
mysql> CREATE DATABASE db1;
-- 再次查看,偏移量已变化
mysql> SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000001 | 535 | | | |
+---------------+----------+--------------+------------------+-------------------+
binlog.000001 是主库二进制日志(binlog)的日志文件名
4.2 自定义 binlog 日志配置
核心配置参数
修改配置文件 /etc/my.cnf.d/mysql-server.cnf 的 [mysqld] 段:
log-bin=/目录名/日志名:指定 binlog 日志的存放路径与文件名前缀server_id=数字:指定主机编号,主从架构必填max_binlog_size=数值m:指定单个 binlog 文件最大容量,默认 1GB
配置实操
bash
# 编辑配置文件
[root@mysql52 ~]# vim /etc/my.cnf.d/mysql-server.cnf
[mysqld]
log-bin=/mylog/mysql52
# 创建日志目录
[root@mysql52 ~]# mkdir /mylog
# 修改目录所有者为mysql用户
[root@mysql52 ~]# chown mysql /mylog
# 重启服务生效
[root@mysql52 ~]# systemctl restart mysqld
# 查看生成的日志文件
[root@mysql52 ~]# ls /mylog/
mysql52.000001 mysql52.index
验证配置生效
sql
[root@mysql52 ~]# mysql
mysql> show master status;
+----------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------+----------+--------------+------------------+-------------------+
| mysql52.000001 | 156 | | | |
+----------------+----------+--------------+------------------+-------------------+
binlog 日志滚动规则
- 默认单个日志文件容量超过 1GB 时,自动创建新的日志文件
- 未写满时,所有写操作都会记录在当前正在使用的日志文件中
- 手动刷新日志:执行
FLUSH LOGS立即生成新日志文件
sql
-- 刷新前
mysql> show master status;
+----------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------+----------+--------------+------------------+-------------------+
| mysql52.000001 | 156 | | | |
+----------------+----------+--------------+------------------+-------------------+
-- 手动刷新日志
mysql> flush logs;
-- 刷新后,生成新日志文件
mysql> show master status;
+----------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------+----------+--------------+------------------+-------------------+
| mysql52.000002 | 156 | | | |
+----------------+----------+--------------+------------------+-------------------+
- 服务重启也会自动生成新的 binlog 文件
bash
[root@mysql52 ~]# systemctl restart mysqld
[root@mysql52 ~]# mysql
mysql> show master status;
+----------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------+----------+--------------+------------------+-------------------+
| mysql52.000003 | 156 | | | |
+----------------+----------+--------------+------------------+-------------------+
4.3 使用 binlog 恢复数据
步骤1:重置日志,准备测试环境
sql
mysql> reset master;
mysql> show master status;
+----------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------+----------+--------------+------------------+-------------------+
| mysql52.000001 | 156 | | | |
+----------------+----------+--------------+------------------+-------------------+
步骤2:执行写操作生成日志
sql
-- 建库
mysql> create database gamedb;
-- 建表
mysql> create table gamedb.t1(name char(10),class char(3));
-- 插入数据
mysql> insert into gamedb.t1 values ("yaya","cloud");
mysql> insert into gamedb.t1 values ("yaya","cloud");
mysql> insert into gamedb.t1 values ("yaya","cloud");
-- 查看数据
mysql> select * from gamedb.t1;
mysql> EXIT;
步骤3:传输日志文件到目标主机
bash
[root@mysql52 ~]# scp /mylog/mysql52.000001 root@192.168.8.50:/root/
步骤4:在 mysql50 主机执行恢复
bash
# 确认日志文件存在
[root@mysql50 ~]# ls /root/mysql52.000001
/root/mysql52.000001
# 使用mysqlbinlog解析并执行恢复
[root@mysql50 ~]# mysqlbinlog /root/mysql52.000001 | mysql -uroot -p'1234.com'
步骤5:验证恢复结果
bash
[root@mysql50 ~]# mysql -uroot -p'1234.com' -e 'select * from gamedb.t1'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------+-------+
| name | class |
+------+-------+
| yaya | cloud |
| yaya | cloud |
| yaya | cloud |
+------+-------+
需要注意的是:binlog 不适合人工手动做常规数据恢复,非常适合机器自动化读取实现主从同步,就是主从同步
五、全文总结
需重点掌握的数据库备份方案:
- 冷备份:停服拷贝物理文件,恢复快但业务中断,适用于维护窗口
- 热备份:服务运行时备份,生产环境主流方案
- 逻辑备份:mysqldump 工具,兼容性强但速度慢,适合小数据量迁移
- binlog 日志备份:记录所有写操作,可实现精确时间点恢复,也是主从同步的基础