12848 字
64 分钟
08:mysql之备份与恢复

[TOC]

08:mysql之备份与恢复#

今日工作任务路线图

flowchart LR
subgraph BottomRow[mysql之备份与恢复]
direction LR
A[mysqldump<br/>备份与恢复] --> B[增量备份<br/>与恢复] --> C[差分备份<br/>与恢复]
end
classDef highlight stroke:#f00,stroke-width:2px;
class E highlight;

一、工作场景#

在一家电商公司的运营过程中,数据库管理员小张日常负责 MySQL 数据库的维护。某天,开发团队要对数据库进行大规模的架构升级,为防止升级过程中出现数据丢失或损坏,小张决定对 MySQL 数据库进行备份。他使用 mysqldump【mysql-当普】 工具,将数据库中的数据和结构导出到一个 SQL 文件中,并把文件存储在多个安全的存储位置。然而,升级过程中出现了意外,数据库中的部分数据丢失。小张迅速行动,利用之前备份的 SQL 文件,使用 mysql 命令将数据恢复到升级前的状态,确保了公司业务的正常运行。

二、为什么学#

学习 MySQL 备份与恢复意义重大。在实际工作里,数据是企业的核心资产,一旦数据库因系统故障、人为误操作、硬件损坏、黑客攻击等原因出现数据丢失或损坏,将给企业带来巨大损失。掌握 MySQL 备份与恢复技术,能在数据丢失时及时恢复,保障业务连续性。同时,在对数据库进行升级、迁移或维护时,提前备份可防止数据意外丢失。此外,学习此技术也是数据库管理员、运维工程师等相关岗位的基本要求,有助于提升个人职业技能,增强在职场上的竞争力。

三、mysqldump【mysql-当普】备份与恢复#

当前任务环节

flowchart LR
subgraph BottomRow[mysql之备份与恢复]
direction LR
A[mysqldump<br/>备份与恢复] --> B[增量备份<br/>与恢复] --> C[差分备份<br/>与恢复]
end
classDef highlight stroke:#f00,stroke-width:2px;
class A highlight;

热备份,备份和恢复数据库服务必须是运行的

3.1 备份数据#

mysqldump【mysql-当普】 主要是把数据导出成一个sql脚本 可以针对某一个表或多个表 也可以针对某一个或多个库

参数命令示例备份范围适用场景
无参数mysqldump 库名 表名单个数据库的表的内容日常单个数据备份
无参数mysqldump 库名 表名 表名...数据库的多个表的内容日常多个数据备份
无参数mysqldump 库名单个数据库的内容日常单个数据库备份
-Bmysqldump -B 库名单个数据库的完整结构+内容数据库迁移
-Bmysqldump -B 库名 库名...多个数据库的完整结构+内容数据库迁移
-Amysqldump -A所有数据库的完整结构+内容全服务器备份、灾难恢复
Terminal window
#备份1张表
[root@mysql50 ~]# mysqldump【mysql-当普】 -uroot -pNSD123456...a moershi salary【晒了瑞】 > /bakdir/moershi_salary【晒了瑞】.sql
#[root@mha ~]# mysqldump -uroot -p123 moershi salary > /root/moershi_salary.sql
#mysqldump【mysql-当普】: [Warning] Using a password on the command line interface can be insecure.
#备份多张表
[root@mysql50 ~]# mysqldump【mysql-当普】 -uroot -pNSD123456...a moershi employees【ing普洛伊s】 departments【迪帕踢门特】 > /bakdir/moershi_employees【ing普洛伊s】_deparments.sql
#[root@mha ~]# mysqldump -uroot -p123 moershi employees departments > /root/moershi_employees_deparments.sql
#mysqldump【mysql-当普】: [Warning] Using a password on the command line interface can be insecure.
#备份1个库
[root@mysql50 ~]# mysqldump【mysql-当普】 -uroot -pNSD123456...a -B moershi > /bakdir/moershi.sql
#[root@mha ~]# mysqldump -uroot -p123 -B moershi > /root/moershi.sql
#mysqldump【mysql-当普】: [Warning] Using a password on the command line interface can be insecure.
#备份多个库
[root@mysql50 ~]# mysqldump【mysql-当普】 -uroot -pNSD123456...a -B studb db1 > /bakdir/studb_db1.sql
#[root@mha ~]# mysqldump -uroot -p123 -B studb db1 > /root/studb_db1.sql
#mysqldump【mysql-当普】: [Warning] Using a password on the command line interface can be insecure.
#备份所有库
[root@mysql50 ~]# mysqldump【mysql-当普】 -uroot -pNSD123456...a -A > /bakdir/allbak.sql
#[root@mha ~]# mysqldump -uroot -p123 -A > /root/allbak.sql
#mysqldump【mysql-当普】: [Warning] Using a password on the command line interface can be insecure.

3.2 恢复数据#

分析:

特点: mysqldump【mysql-当普】 备份和恢复数据时会锁表,锁表期间无法对表做写访问 mysqldump【mysql-当普】适合备份数据量比较小的数据或在数据库服务器访问量少的时候备份。

[root@mysql50 ~]# mysql -uroot -pNSD123456...a
-- [root@mha ~]# mysql -uroot -p123
-- 删除库
mysql> drop【卓-普】 database【得塔-贝斯】 moershi;
-- mysql> drop database moershi;
-- Query OK, 6 rows affected (0.57 sec)
mysql> exit【诶西特】
Bye
-- 恢复数据
[root@mysql50 ~]# mysql -uroot -pNSD123456...a < /bakdir/moershi.sql
-- [root@mha ~]# mysql -uroot -p123 < /root/moershi.sql
-- mysql: [Warning] Using a password on the command line interface can be insecure.
-- 登陆
[root@mysql50 ~]# mysql -uroot -pNSD123456...a
-- [root@mha ~]# mysql -uroot -p123
-- 进库
mysql> use moershi;
-- mysql> use moershi;
-- 看表
mysql> show【瘦】 tables【忒-部s】;
-- mysql> show tables;
+------------------+
| Tables_in_moershi |
+------------------+
| departments |
| employees |
| salary |
| stu4 |
| user |
| wage_grade |
+------------------+
6 rows in set (0.00 sec)
-- 删除表记录
mysql> delete【迪利特】 from【弗乱】 salary【晒了瑞】;
Query OK, 8055 rows affected (0.11 sec)
mysql> exit【诶西特】
Bye
-- 使用备份文件恢复数据
[root@mysql50 ~]# mysql -uroot -pNSD123456...a moershi < /bakdir/moershi_salary【晒了瑞】.sql
-- mysql: [Warning] Using a password on the command line interface can be insecure.
-- 登陆服务
[root@mysql50 ~]# mysql -uroot -pNSD123456...a
-- [root@mha ~]# mysql -uroot -p123
-- 查看行数
mysql> select【涩莱克特】 count【kàn特】(*) from【弗乱】 moershi.salary【晒了瑞】;
-- mysql> select count(*) from moershi.salary;
+----------+
| count(*) |
+----------+
| 8055 |
+----------+
1 row in set (0.00 sec)

四、增量备份与恢复#

当前任务环节

flowchart LR
subgraph BottomRow[mysql之备份与恢复]
direction LR
A[mysqldump<br/>备份与恢复] --> B[增量备份<br/>与恢复] --> C[差分备份<br/>与恢复]
end
classDef highlight stroke:#f00,stroke-width:2px;
class B highlight;

4.1 准备2台数据库服务器#

主机名IP地址说明
mysql50192.168.90.50用于备份数据库
mysql51192.168.90.51用于恢复数据库

mysql51机器的IP配置和主机名

Terminal window
[root@localhost ~]# nmcli connection【肯耐申】 modify【莫迪fái】 ens160 ipv4.addresses【额拽西斯】 192.168.90.51/24 autoconnect【奥特欧 坑聂特】 yes
#[root@mha ~]# nmcli connection modify eth0 ipv4.addresses 192.168.88.40/24 autoconnect yes
[root@localhost ~]# nmcli connection【肯耐申】 up【啊普】 ens160
#[root@mha ~]# nmcli connection up eth1
[root@mysql51 ~]# hostnamectl【厚斯内姆 ctl】 set-hostname【赛特-厚斯内姆】 mysql51
#[root@mha ~]# hostnamectl set-hostname mha

增量备份和差异备份优缺点#

增量备份

  • 定义:增量备份只备份自上一次备份(无论是完全备份、增量备份还是差异备份)以来发生变化的数据。

  • 工作原理:首先需要一个完整的备份(基础备份),然后每次增量备份都只备份相对于上一次备份后变化的数据。

  • 优点:备份速度快,占用空间小,因为每次只备份变化的数据。

  • 缺点:恢复数据时,需要先恢复完整备份,然后按照时间顺序依次恢复所有的增量备份,直到指定的时间点。恢复过程复杂且耗时,如果中间任何一个备份损坏,可能导致整个恢复链失效。

  • 适用场景:数据量大,备份窗口短,但对恢复时间要求不高的场景。

    当前的备份是基于上一次备份做增量的备份 一般第一次备份要完全备份 第一次:全量—>增加了a 第二次: 备份a--->增加了b 第三次: 备份b--->增加了c 第四次: 备份c--->增加了d

    增量备份做数据恢复 全量<---备份a 全量<---备份b 全量<---备份c 最终 全量(abc)

差异备份

  • 定义:差异备份备份自上一次完整备份以来所有发生变化的数据。

  • 工作原理:首先需要一个完整备份,然后每次差异备份都会备份自上次完整备份以来所有变化的数据。因此,第二次差异备份会包含第一次差异备份的内容,第三次会包含第一次和第二次的内容,以此类推。

  • 优点:恢复时只需要完整备份和最近一次的差异备份,恢复过程相对简单。

  • 缺点:随着时间推移,差异备份的大小会越来越大,因为每次都要备份自完整备份以来的所有变化。备份时间可能会逐渐增加。

  • 适用场景:数据量变化不大,且希望恢复过程相对简单的场景。

    当前的备份是基于第一次备份做增量的备份 一般第一次备份要完全备份 第一次:全量—>增加了a 第二次: 备份a--->增加了b 第三次: 备份ab--->增加了c 第四次: 备份abc--->增加了d 全量<—备份abc 最终 全量(abc)

对比总结:

  • 备份内容:增量备份只备份上一次备份后的变化,而差异备份备份自上次完整备份后的所有变化。
  • 备份空间和速度:增量备份占用空间小,速度快;差异备份随着时间推移,占用空间和备份时间都会增加。
  • 恢复过程:增量恢复需要完整备份和所有增量备份,步骤多,易出错;差异恢复只需要完整备份和最近一次差异备份,相对简单。

PERCONA【帕扣娜】 xtrabackup【xtra-拜克阿普】是一款强大的在线热备份工具,备份过程中不锁库表,适合生产环境。支持完全备份与恢复、增量备份与恢复、差异备份与恢复。

在192.168.90.50主机完成备份与恢复的练习 。

4.2 数据增量备份#

安装软件(在mysql50 、MySQL51 两台主机都要安装)

Terminal window
#一、使用YUM下载方式,下载RPM包:
[root@mysql50 ~]# yum -y install【因-斯多】 https://repo.percona.com/yum/percona-release-latest.noarch.rpm
#[root@mha ~]# yum -y install https://repo.percona.com/yum/percona-release-latest.noarch.rpm
#二、启用percona【帕扣娜】库:
[root@mysql50 ~]# percona【帕扣娜】-release【率利斯】 enable【ing 内 步】-only【欧利】 tools【兔斯】 release【率利斯】
#[root@mha ~]# percona-release enable-only tools release
#三、依赖包下载
[root@mysql50 ~]# yum -y install【因-斯多】 lz4 zstd
#[root@mha ~]# yum -y install lz4 zstd
#四、安装percona【帕扣娜】-xtrabackup【xtra-拜克阿普】
[root@mysql50 ~]# yum -y install【因-斯多】 percona【帕扣娜】-xtrabackup【xtra-拜克阿普】-80
#[root@mha ~]# yum -y install percona-xtrabackup-80

增量备份(在mysql50主机 完成增量备份练习)

—host:备份的主机IP

—user: 数据库的用户

—password【帕斯沃德】: 数据库的密码

—backup【拜克阿普】:启动备份过程,是最基本的备份启动选项

—target【塔géi特】-dir【迪尔】: 指定备份文件的存储目录

—datadir【得塔-迪尔】: 数据库文件目录

—incremental【因葵孟透】-basedir【贝斯迪尔】:指定增量备份的基础目录,即上一次备份的目录

周一完全备份(备份所有数据)

对数据做增量备份前,必须先有一次备份,也就是首次备份,通常是备份所有数据;比如每周周一完全备份,周二到周日增量备份。

Terminal window
#全量备份
[root@mysql50 ~]# xtrabackup【xtra-拜克阿普】 --host=127.0.0.1 --user=root --password【帕斯沃德】=NSD123456...a --backup【拜克阿普】 --target【塔géi特】-dir【迪尔】=/fullbak【fò-拜克】 --datadir【得塔-迪尔】=/var/lib/mysql
#[root@mha ~]# xtrabackup --host=127.0.0.1 --user=root --password=123 --backup --target-dir=/fullbak --datadir=/var/lib/mysql
……
230530 18:18:48 [00] ...done
xtrabackup【xtra-拜克阿普】: Transaction log of lsn (24822878) to (24822898) was copied.
230530 18:18:50 completed OK!
#插入新数据 (可以插入多行)
mysql> insert【因涩特】 into【因兔】 moershi.salary【晒了瑞】(date,employee_id,basic【贝斯克】,bonus【波诺斯】) values【挖柳斯】("20250610",18,25000,8000);
#mysql> insert into moershi.salary(date,employee_id,basic,bonus) values("20250610",18,25000,8000);
#Query OK, 1 row affected (0.05 sec)

周二增量备份(备份周一备份后新产生的数据)

Terminal window
[root@mysql50 ~]# xtrabackup【xtra-拜克阿普】 --host=127.0.0.1 --user=root --password【帕斯沃德】=NSD123456...a --backup【拜克阿普】 --target【塔géi特】-dir【迪尔】=/new2 --incremental【因葵孟透】-basedir【贝斯迪尔】=/fullbak【fò-拜克】 --datadir【得塔-迪尔】=/var/lib/mysql
#[root@mha ~]# xtrabackup --host=127.0.0.1 --user=root --password=123 --backup --target-dir=/new2 --incremental-basedir=/fullbak --datadir=/var/lib/mysql
……
……
230530 18:33:52 [00] ...done
xtrabackup【xtra-拜克阿普】: Transaction log of lsn (24827173) to (24827183) was copied.
230530 18:33:53 completed OK!
#插入新数据 (可以插入多行)
mysql> insert【因涩特】 into【因兔】 moershi.salary【晒了瑞】(date,employee_id,basic【贝斯克】,bonus【波诺斯】) values【挖柳斯】("20250710",18,25000,8000);
#mysql> insert into moershi.salary(date,employee_id,basic,bonus) values("20250710",18,25000,8000);
#Query OK, 1 row affected (0.11 sec)

周三增量备份(备份周二备份后新产生的数据)

Terminal window
[root@mysql50 ~]# xtrabackup【xtra-拜克阿普】 --host=127.0.0.1 --user=root --password【帕斯沃德】=NSD123456...a --backup【拜克阿普】 --target【塔géi特】-dir【迪尔】=/new3 --incremental【因葵孟透】-basedir【贝斯迪尔】=/new2 --datadir【得塔-迪尔】=/var/lib/mysql
#[root@mha ~]# xtrabackup --host=127.0.0.1 --user=root --password=123 --backup --target-dir=/new3 --incremental-basedir=/fullbak --datadir=/var/lib/mysql
……
……
230530 18:46:17 [00] ...done
xtrabackup【xtra-拜克阿普】: Transaction log of lsn (24832526) to (24832536) was copied.
230530 18:46:18 completed OK!
#插入新数据 (可以插入多行)
mysql> insert【因涩特】 into【因兔】 moershi.salary【晒了瑞】(date,employee_id,basic【贝斯克】,bonus【波诺斯】) values【挖柳斯】("20250710",18,25000,8000);
#mysql> insert into moershi.salary(date,employee_id,basic,bonus) values("20250710",18,25000,8000);
#Query OK, 1 row affected (0.08 sec)

周四增量备份(备份周三备份后新产生的数据)

Terminal window
[root@mysql50 ~]# xtrabackup【xtra-拜克阿普】 --host=127.0.0.1 --user=root --password【帕斯沃德】=NSD123456...a --backup【拜克阿普】 --target【塔géi特】-dir【迪尔】=/new4 --incremental【因葵孟透】-basedir【贝斯迪尔】=/new3 --datadir【得塔-迪尔】=/var/lib/mysql
#[root@mha ~]# xtrabackup --host=127.0.0.1 --user=root --password=123 --backup --target-dir=/new4 --incremental-basedir=/fullbak --datadir=/var/lib/mysql
……
……
230530 18:53:41 [00] ...done
xtrabackup【xtra-拜克阿普】: Transaction log of lsn (24837561) to (24837571) was copied.
230530 18:53:42 completed OK!
#插入新数据 (可以插入多行)
mysql> insert【因涩特】 into【因兔】 moershi.salary【晒了瑞】(date,employee_id,basic【贝斯克】,bonus【波诺斯】) values【挖柳斯】("20250710",18,25000,8000);
#mysql> insert into moershi.salary(date,employee_id,basic,bonus) values("20250710",18,25000,8000);
#Query OK, 1 row affected (0.05 sec)

周五增量备份(备份周四备份后新产生的数据)

Terminal window
[root@mysql50 ~]# xtrabackup【xtra-拜克阿普】 --host=127.0.0.1 --user=root --password【帕斯沃德】=NSD123456...a --backup【拜克阿普】 --target【塔géi特】-dir【迪尔】=/new5 --incremental【因葵孟透】-basedir【贝斯迪尔】=/new4 --datadir【得塔-迪尔】=/var/lib/mysql
#[root@mha ~]# xtrabackup --host=127.0.0.1 --user=root --password=123 --backup --target-dir=/new5 --incremental-basedir=/fullbak --datadir=/var/lib/mysql
……
……
230530 18:58:50 [00] ...done
xtrabackup【xtra-拜克阿普】: Transaction log of lsn (24841645) to (24841655) was copied.
230530 18:58:51 completed OK!
#插入新数据 (可以插入多行)
mysql> insert【因涩特】 into【因兔】 moershi.salary【晒了瑞】(date,employee_id,basic【贝斯克】,bonus【波诺斯】) values【挖柳斯】("20250710",18,25000,8000);
#mysql> insert into moershi.salary(date,employee_id,basic,bonus) values("20250710",18,25000,8000);
#Query OK, 1 row affected (0.04 sec)

周六增量备份(备份周五备份后新产生的数据)

Terminal window
[root@mysql50 ~]# xtrabackup【xtra-拜克阿普】 --host=127.0.0.1 --user=root --password【帕斯沃德】=NSD123456...a --backup【拜克阿普】 --target【塔géi特】-dir【迪尔】=/new6 --incremental【因葵孟透】-basedir【贝斯迪尔】=/new5 --datadir【得塔-迪尔】=/var/lib/mysql
#[root@mha ~]# xtrabackup --host=127.0.0.1 --user=root --password=123 --backup --target-dir=/new6 --incremental-basedir=/fullbak --datadir=/var/lib/mysql
……
……
230530 19:00:55 [00] ...done
xtrabackup【xtra-拜克阿普】: Transaction log of lsn (24848404) to (24848414) was copied.
230530 19:00:56 completed OK!
#插入新数据 (可以插入多行)
mysql> insert【因涩特】 into【因兔】 moershi.salary【晒了瑞】(date,employee_id,basic【贝斯克】,bonus【波诺斯】) values【挖柳斯】("20250710",18,25000,8000);
#mysql> insert into moershi.salary(date,employee_id,basic,bonus) values("20250710",18,25000,8000);
#Query OK, 1 row affected (0.06 sec)

周日增量备份(备份周六备份后新产生的数据)

Terminal window
[root@mysql50 ~]# xtrabackup【xtra-拜克阿普】 --host=127.0.0.1 --user=root --password【帕斯沃德】=NSD123456...a --backup【拜克阿普】 --target【塔géi特】-dir【迪尔】=/new7 --incremental【因葵孟透】-basedir【贝斯迪尔】=/new6 --datadir【得塔-迪尔】=/var/lib/mysql
#[root@mha ~]# xtrabackup --host=127.0.0.1 --user=root --password=123 --backup --target-dir=/new7 --incremental-basedir=/fullbak --datadir=/var/lib/mysql
……
……
230530 19:00:55 [00] ...done
xtrabackup【xtra-拜克阿普】: Transaction log of lsn (24848404) to (24848414) was copied.
230530 19:00:56 completed OK!
[root@mysql50 ~]#

4.3 数据增量恢复#

增量恢复数据步骤:

  1. 准备恢复数据
  2. 合并数据
  3. 清空数据库目录
  4. 拷贝数据
  5. 修改数据库目录所有者/组用户为mysql
  6. 重启数据库服务

具体操作如下:

MySQL51 拷贝 MySQL50 的备份文件到 本机的根目录下

[root@mysql51 ~]# scp –r root@192.168.90.50:/fullbak【fò-拜克】 /
[root@mysql51 ~]# scp –r root@192.168.90.50:/new2 /
[root@mysql51 ~]# scp –r root@192.168.90.50:/new3 /
[root@mysql51 ~]# scp –r root@192.168.90.50:/new4 /
[root@mysql51 ~]# scp –r root@192.168.90.50:/new5 /
[root@mysql51 ~]# scp –r root@192.168.90.50:/new6 /
[root@mysql51 ~]# scp –r root@192.168.90.50:/new7 /

在MySQL51主机使用备份文件恢复数据

—prepare【普瑞-撇尔】:对备份数据进行预处理,回滚未提交的事务并同步已提交的事务至数据文件,使数据文件处于一致性状态,以便用于恢复

—apply-log-only【欧利】:在准备备份时使用,表示只应用重做日志(redo log),不回滚未提交的事务,常用于增量备份准备

—target【塔géi特】-dir【迪尔】:指定备份文件的存储目录

—incremental【因葵孟透】-dir【迪尔】:指定增量备份的存储目录

1)、准备恢复数据

[root@mysql51 ~]# xtrabackup【xtra-拜克阿普】 --prepare【普瑞-撇尔】 --apply-log-only【欧利】 --target【塔géi特】-dir【迪尔】=/fullbak【fò-拜克】
……
……
Log background threads are being closed...
Shutdown completed; log sequence number 24822898
Number of pools: 1
250630 14:32:14 completed OK!
[root@mysql51 ~]#

2)、合并数据

//将周二的增量数据拷贝到周一备份目录里,合并后周一的目录里存放的是周一 + 周二 的数据
[root@mysql51 ~]# xtrabackup【xtra-拜克阿普】 --prepare【普瑞-撇尔】 --apply-log-only【欧利】 --target【塔géi特】-dir【迪尔】=/fullbak【fò-拜克】 --incremental【因葵孟透】-dir【迪尔】=/new2
……
……
250630 14:40:05 [00] Copying /new2/binlog.index to ./binlog.index
250630 14:40:05 [00] ...done
250630 14:40:05 completed OK!
[root@mysql51 ~]#
//将周三的增量数据拷贝到周一备份目录里,合并后周一的目录里存放的是周一 + 周二 + 周三 的数据
[root@mysql51 ~]# xtrabackup【xtra-拜克阿普】 --prepare【普瑞-撇尔】 --apply-log-only【欧利】 --target【塔géi特】-dir【迪尔】=/fullbak【fò-拜克】 --incremental【因葵孟透】-dir【迪尔】=/new3
……
……
250630 15:00:37 [00] Copying /new3/binlog.index to ./binlog.index
250630 15:00:37 [00] ...done
250630 15:00:37 completed OK!
[root@mysql51 ~]#
//将周四的增量数据拷贝到周一备份目录里,合并后周一的目录里存放的是周一 + 周二 + 周三 +周四的数据
[root@mysql51 ~]# xtrabackup【xtra-拜克阿普】 --prepare【普瑞-撇尔】 --apply-log-only【欧利】 --target【塔géi特】-dir【迪尔】=/fullbak【fò-拜克】 --incremental【因葵孟透】-dir【迪尔】=/new4
……
……
250630 15:00:37 [00] Copying /new4/binlog.index to ./binlog.index
250630 15:00:37 [00] ...done
250630 15:00:37 completed OK!
[root@mysql51 ~]#
//将周五的增量数据拷贝到周一备份目录里,合并后周一的目录里存放的是周一 + 周二 + 周三 +周四+周五的数据
[root@mysql51 ~]# xtrabackup【xtra-拜克阿普】 --prepare【普瑞-撇尔】 --apply-log-only【欧利】 --target【塔géi特】-dir【迪尔】=/fullbak【fò-拜克】 --incremental【因葵孟透】-dir【迪尔】=/new5
……
……
250630 15:00:37 [00] Copying /new5/binlog.index to ./binlog.index
250630 15:00:37 [00] ...done
250630 15:00:37 completed OK!
[root@mysql51 ~]#
//将周六的增量数据拷贝到周一备份目录里,合并后周一的目录里存放的是周一 + 周二 + 周三 +周四+周五+周六的数据
[root@mysql51 ~]# xtrabackup【xtra-拜克阿普】 --prepare【普瑞-撇尔】 --apply-log-only【欧利】 --target【塔géi特】-dir【迪尔】=/fullbak【fò-拜克】 --incremental【因葵孟透】-dir【迪尔】=/new6
……
……
250630 15:00:37 [00] Copying /new6/binlog.index to ./binlog.index
250630 15:00:37 [00] ...done
250630 15:00:37 completed OK!
[root@mysql51 ~]#
//将周日的增量数据拷贝到周一备份目录里,合并后周一的目录里存放的是周一 + 周二 + 周三 +周四+周五+周六+周日的数据
[root@mysql51 ~]# xtrabackup【xtra-拜克阿普】 --prepare【普瑞-撇尔】 --apply-log-only【欧利】 --target【塔géi特】-dir【迪尔】=/fullbak【fò-拜克】 --incremental【因葵孟透】-dir【迪尔】=/new7
……
……
250630 15:00:37 [00] Copying /new7/binlog.index to ./binlog.index
250630 15:00:37 [00] ...done
250630 15:00:37 completed OK!
[root@mysql51 ~]#
[root@mysql51 ~]# rm -rf /var/lib/mysql/*
[root@mysql51 ~]# xtrabackup【xtra-拜克阿普】 --prepare【普瑞-撇尔】 --target【塔géi特】-dir【迪尔】=/fullbak【fò-拜克】
[root@mysql51 ~]# xtrabackup【xtra-拜克阿普】 --copy-back --target【塔géi特】-dir【迪尔】=/fullbak【fò-拜克】
[root@mysql51 ~]# chown -R mysql:mysql /var/lib/mysql

6)重启数据库服务

[root@mysql51 ~]# systemctl restart mysqld

7)连接服务查看数据

[root@mysql51 ~]# mysql -uroot -pNSD123456...a
mysql> select【涩莱克特】 count【kàn特】(*) from【弗乱】 moershi.salary【晒了瑞】 where date=20250710;
+----------+
| count(*) |
+----------+
| 75 |
+----------+
1 row in set (0.01 sec)
mysql> select【涩莱克特】 count【kàn特】(*) from【弗乱】 moershi.salary【晒了瑞】 where not date=20250710;
+----------+
| count(*) |
+----------+
| 8067 |
+----------+
1 row in set (0.00 sec)

五、差异备份与恢复#

当前任务环节

flowchart LR
subgraph BottomRow[mysql之备份与恢复]
direction LR
A[mysqldump<br/>备份与恢复] --> B[增量备份<br/>与恢复] --> C[差分备份<br/>与恢复]
end
classDef highlight stroke:#f00,stroke-width:2px;
class C highlight;

差异备份:备份完全备份后,新产生的数据。

PERCONA【帕扣娜】 xtrabackup【xtra-拜克阿普】是一款强大的在线热备份工具,备份过程中不锁库表,适合生产环境。支持差异备份与恢复。

在192.168.90.50主机完成差异备份

5.1 差异备份#

差异备份

对数据做差异备份前,必须先有一次备份,也就是首次备份,通常是备份所有数据;比如每周周一完全备份,周二到周日差异备份。

//周一完全备份
[root@mysql50 ~]# xtrabackup【xtra-拜克阿普】 --host=127.0.0.1 --user=root --password【帕斯沃德】=NSD123456...a --backup【拜克阿普】 --target【塔géi特】-dir【迪尔】=/allbak --datadir【得塔-迪尔】=/var/lib/mysql
……
……
260630 17:10:02 [00] Writing /allbak/xtrabackup【xtra-拜克阿普】_info
260630 17:10:02 [00] ...done
xtrabackup【xtra-拜克阿普】: Transaction log of lsn (24881353) to (24881373) was copied.
260630 17:10:03 completed OK!
[root@mysql50 ~]#
//插入新数据 (可以插入多行)
mysql> insert【因涩特】 into【因兔】 tarena.salary【晒了瑞】(date,employee_id,basic【贝斯克】,bonus【波诺斯】) values【挖柳斯】("20250810",18,25000,8000);

周二差异备份,备份周一备份后新产生的数据

[root@mysql50 ~]# xtrabackup【xtra-拜克阿普】 --host=127.0.0.1 --user=root --password【帕斯沃德】=NSD123456...a --backup【拜克阿普】 --target【塔géi特】-dir【迪尔】=/dir2 --incremental【因葵孟透】-basedir【贝斯迪尔】=/allbak --datadir【得塔-迪尔】=/var/lib/mysql
……
……
260630 17:23:56 [00] Writing /dir2/xtrabackup【xtra-拜克阿普】_info
260630 17:23:56 [00] ...done
xtrabackup【xtra-拜克阿普】: Transaction log of lsn (24886741) to (24886751) was copied.
260630 17:23:58 completed OK!
[root@mysql50 ~]#
//插入新数据 (可以插入多行)
mysql> insert【因涩特】 into【因兔】 tarena.salary【晒了瑞】(date,employee_id,basic【贝斯克】,bonus【波诺斯】) values【挖柳斯】("20250810",18,25000,8000);

周三差异备份,备份周一备份后新产生的数据

[root@mysql50 ~]# xtrabackup【xtra-拜克阿普】 --host=127.0.0.1 --user=root --password【帕斯沃德】=NSD123456...a --backup【拜克阿普】 --target【塔géi特】-dir【迪尔】=/dir3 --incremental【因葵孟透】-basedir【贝斯迪尔】=/allbak --datadir【得塔-迪尔】=/var/lib/mysql
……
……
260630 17:27:10 [00] Writing /dir3/xtrabackup【xtra-拜克阿普】_info
260630 17:27:10 [00] ...done
xtrabackup【xtra-拜克阿普】: Transaction log of lsn (24892043) to (24892063) was copied.
260630 17:27:11 completed OK!
[root@mysql50 ~]#
//插入新数据 (可以插入多行)
mysql> insert【因涩特】 into【因兔】 tarena.salary【晒了瑞】(date,employee_id,basic【贝斯克】,bonus【波诺斯】) values【挖柳斯】("20250810",18,25000,8000);

周四差异备份,备份周一备份后新产生的数据

[root@mysql50 ~]# xtrabackup【xtra-拜克阿普】 --host=127.0.0.1 --user=root --password【帕斯沃德】=NSD123456...a --backup【拜克阿普】 --target【塔géi特】-dir【迪尔】=/dir4 --incremental【因葵孟透】-basedir【贝斯迪尔】=/allbak --datadir【得塔-迪尔】=/var/lib/mysql
……
……
230531 17:31:00 [00] Writing /dir4/xtrabackup【xtra-拜克阿普】_info
230531 17:31:00 [00] ...done
xtrabackup【xtra-拜克阿普】: Transaction log of lsn (24900560) to (24900580) was copied.
230531 17:31:01 completed OK!
[root@mysql50 ~]#
//插入新数据 (可以插入多行)
mysql> insert【因涩特】 into【因兔】 tarena.salary【晒了瑞】(date,employee_id,basic【贝斯克】,bonus【波诺斯】) values【挖柳斯】("20250810",18,25000,8000);

周五差异备份,备份周一备份后新产生的数据

[root@mysql50 ~]# xtrabackup【xtra-拜克阿普】 --host=127.0.0.1 --user=root --password【帕斯沃德】=NSD123456...a --backup【拜克阿普】 --target【塔géi特】-dir【迪尔】=/dir5 --incremental【因葵孟透】-basedir【贝斯迪尔】=/allbak --datadir【得塔-迪尔】=/var/lib/mysql
……
……
230531 17:32:38 [00] Writing /dir5/xtrabackup【xtra-拜克阿普】_info
230531 17:32:38 [00] ...done
xtrabackup【xtra-拜克阿普】: Transaction log of lsn (24906902) to (24906912) was copied.
230531 17:32:39 completed OK!
[root@mysql50 ~]#
//插入新数据 (可以插入多行)
mysql> insert【因涩特】 into【因兔】 tarena.salary【晒了瑞】(date,employee_id,basic【贝斯克】,bonus【波诺斯】) values【挖柳斯】("20250810",18,25000,8000);

周六差异备份,备份周一备份后新产生的数据

[root@mysql50 ~]# xtrabackup【xtra-拜克阿普】 --host=127.0.0.1 --user=root --password【帕斯沃德】=NSD123456...a --backup【拜克阿普】 --target【塔géi特】-dir【迪尔】=/dir6 --incremental【因葵孟透】-basedir【贝斯迪尔】=/allbak --datadir【得塔-迪尔】=/var/lib/mysql
……
……
230531 17:41:01 [00] Writing /dir6/xtrabackup【xtra-拜克阿普】_info
230531 17:41:01 [00] ...done
xtrabackup【xtra-拜克阿普】: Transaction log of lsn (24914729) to (24914739) was copied.
230531 17:41:02 completed OK!
[root@mysql50 ~]#
-- 插入新数据 (可以插入多行)
mysql> insert【因涩特】 into【因兔】 tarena.salary【晒了瑞】(date,employee_id,basic【贝斯克】,bonus【波诺斯】) values【挖柳斯】("20250810",18,25000,8000);

周日差异,备份备份周一备份后新产生的数据

Terminal window
[root@mysql50 ~]# xtrabackup【xtra-拜克阿普】 --host=127.0.0.1 --user=root --password【帕斯沃德】=NSD123456...a --backup【拜克阿普】 --target【塔géi特】-dir【迪尔】=/dir7 --incremental【因葵孟透】-basedir【贝斯迪尔】=/allbak --datadir【得塔-迪尔】=/var/lib/mysql
……
……
230531 17:43:16 [00] Writing /dir7/xtrabackup【xtra-拜克阿普】_info
230531 17:43:16 [00] ...done
xtrabackup【xtra-拜克阿普】: Transaction log of lsn (24920772) to (24920782) was copied.
230531 17:43:17 completed OK!
[root@mysql50 ~]#

5.2 差异恢复#

差异恢复数据步骤:

  1. 准备恢复数据
  2. 合并数据
  3. 清空数据库目录
  4. 拷贝数据
  5. 修改数据库目录所有者/组用户为mysql
  6. 重启数据库服务

具体操作如下:

MySQL51 拷贝 MySQL50 的备份文件到 本机的根目录下

Terminal window
[root@mysql51 ~]# scp –r root@192.168.90.50:/allbak /
[root@mysql51 ~]# scp –r root@192.168.90.50:/dir7 /

在MySQL51主机使用备份文件恢复数据

1)、准备恢复数据

Terminal window
[root@mysql51 ~]# xtrabackup【xtra-拜克阿普】 --prepare【普瑞-撇尔】 --apply-log-only【欧利】 --target【塔géi特】-dir【迪尔】=/allbak
……
……
Log background threads are being closed...
Shutdown completed; log sequence number 24881373
Number of pools: 1
230531 17:59:06 completed OK!
[root@mysql51 ~]#

2)、合并数据

//将周日的差异备份与周一的完全备份合并,因为周日的差异备份包扩周二+周日的所有数据
[root@mysql51 ~]# xtrabackup【xtra-拜克阿普】 --prepare【普瑞-撇尔】 --apply-log-only【欧利】 --target【塔géi特】-dir【迪尔】=/allbak --incremental【因葵孟透】-dir【迪尔】=/dir7
……
……
230531 18:05:08 [00] Copying /dir7/binlog.000029 to ./binlog.000029
230531 18:05:08 [00] ...done
230531 18:05:08 [00] Copying /dir7/binlog.index to ./binlog.index
230531 18:05:08 [00] ...done
230531 18:05:08 completed OK!
[root@mysql51 ~]#
[root@mysql51 ~]# rm -rf /var/lib/mysql/*
[root@mysql51 ~]# xtrabackup【xtra-拜克阿普】 --prepare【普瑞-撇尔】 --target【塔géi特】-dir【迪尔】=/allbak
[root@mysql51 ~]# xtrabackup【xtra-拜克阿普】 --copy-back --target【塔géi特】-dir【迪尔】=/allbak
[root@mysql51 ~]# chown -R mysql:mysql /var/lib/mysql

3)重启数据库服务

[root@mysql51 ~]# systemctl restart mysqld

4)连接服务查看数据

[root@mysql51 ~]# mysql -uroot -pNSD123456...a
mysql> select【涩莱克特】 count【kàn特】(*) from【弗乱】 tarena.salary【晒了瑞】 where date=20250810;
+----------+
| count(*) |
+----------+
| 75 |
+----------+
1 row in set (0.01 sec)
mysql> select【涩莱克特】 count【kàn特】(*) from【弗乱】 tarena.salary【晒了瑞】 where not date=20250810;
+----------+
| count(*) |
+----------+
| 8067 |
+----------+
1 row in set (0.00 sec)

全量备份#

Terminal window
### 全量备份步骤
以下是使用 `xtrabackup` 进行全量备份的命令:
[root@mha ~]# xtrabackup --backup --target-dir=/path/to/backup
#- `--backup`:表示执行备份操作。
#- `--target-dir`:指定备份文件的存储目录。
备份完成后,需要对备份进行准备,以确保备份数据处于一致状态:
[root@mha ~]# xtrabackup --prepare --target-dir=/path/to/backup
#- `--prepare`:对备份数据进行准备,应用事务日志。
### 恢复步骤
#### 1. 停止 MySQL 服务
在恢复备份之前,需要停止正在运行的 MySQL 服务,以避免数据冲突。
[root@mha ~]# sudo systemctl stop mysql
#### 2. 清空 MySQL 数据目录
为了确保恢复的数据是完整的,需要清空 MySQL 数据目录中的现有数据。
[root@mha ~]# sudo rm -rf /var/lib/mysql/*
#### 3. 恢复备份数据
将备份数据复制到 MySQL 数据目录。
[root@mha ~]# sudo xtrabackup --copy-back --target-dir=/path/to/backup
#- `--copy-back`:将备份数据复制回 MySQL 数据目录。
#### 4. 修改文件权限
恢复数据后,需要确保 MySQL 数据目录及其文件的权限正确。
[root@mha ~]# sudo chown -R mysql:mysql /var/lib/mysql
#### 5. 启动 MySQL 服务
完成上述步骤后,可以启动 MySQL 服务。
[root@mha ~]# sudo systemctl start mysql
#### 6. 验证恢复结果
可以登录 MySQL 并检查数据库和表是否已成功恢复。
[root@mha ~]# mysql -u root -p

增量备份恢复#

Terminal window
#准备恢复数据。使用 `--apply-log-only`只应用重做日志,不回滚为后续增量备份应用做准备。因为在增量备份中,基础备份必须保持事务状态,以便后续的增量备份能够正确应用。如果提前回滚了未提交事务,那么增量备份应用时可能会丢失一些事务信息。
[root@mha ~]# sudo xtrabackup --prepare --apply-log-only --target-dir=/fullbak
#合并增量数据,需要把所有的增量备份数据全部合并,不然会造成数据缺失
[root@mha ~]# sudo xtrabackup --prepare --apply-log-only --target-dir=/fullbak --incremental-dir=/new1
[root@mha ~]# sudo xtrabackup --prepare --apply-log-only --target-dir=/fullbak --incremental-dir=/new2
[root@mha ~]# sudo xtrabackup --prepare --apply-log-only --target-dir=/fullbak --incremental-dir=/new3
# 停止 MySQL 服务。在恢复备份之前,需要停止正在运行的 MySQL 服务,以避免数据冲突。
[root@mha ~]# sudo systemctl stop mysql
# 清空 MySQL 数据目录。为了确保恢复的数据是完整的,需要清空 MySQL 数据目录中的现有数据。
[root@mha ~]# sudo rm -rf /var/lib/mysql/*
# 最终准备预处理备份数据。应用重做日志(redo log)到数据文件,将数据文件前滚到备份结束时的状态,使备份数据处于一致状态,可以用于恢复。
[root@mha ~]# sudo xtrabackup --prepare --target-dir=/fullbak
# 恢复备份数据。将备份数据复制到 MySQL 数据目录。
[root@mha ~]# sudo xtrabackup --copy-back --target-dir=/fullbak
# 修改文件权限。恢复数据后,需要确保 MySQL 数据目录及其文件的权限正确。
[root@mha ~]# sudo chown -R mysql:mysql /var/lib/mysql
# 启动 MySQL 服务。完成上述步骤后,可以启动 MySQL 服务。
[root@mha ~]# sudo systemctl start mysql
# 验证恢复结果。可以登录 MySQL 并检查数据库和表是否已成功恢复。
[root@mha ~]# mysql -u root -p

差异备份恢复#

Terminal window
# 差异备份恢复步骤:
# 1. 准备基础全量备份(使用 --apply-log-only 保持事务状态)
[root@mha ~]# sudo xtrabackup --prepare --apply-log-only --target-dir=/fullbak
# 原因:基础备份必须保持事务状态,以便后续的差异备份能够正确应用。
# 如果提前回滚了未提交事务,差异备份应用时可能会丢失事务信息。
# 2. 应用最后一次差异备份(直接完整准备,不使用 --apply-log-only)
[root@mha ~]# sudo xtrabackup --prepare --target-dir=/fullbak --incremental-dir=/diff_backup
# 原因:差异备份基于同一个全量备份,这是最后一个备份步骤,需要完成事务回滚,使数据达到一致状态。
# 不需要使用 --apply-log-only,因为后面没有更多的备份要应用。
# 3. 停止 MySQL 服务
[root@mha ~]# sudo systemctl stop mysql
# 原因:在恢复备份之前,需要停止正在运行的 MySQL 服务,以避免数据冲突。
# 4. 备份并清空 MySQL 数据目录
[root@mha ~]# sudo mv /var/lib/mysql /var/lib/mysql_backup_$(date +%Y%m%d)
[root@mha ~]# sudo mkdir /var/lib/mysql
# 原因:为了确保恢复的数据是完整的,需要清空 MySQL 数据目录中的现有数据。
# 5. 恢复备份数据到 MySQL 数据目录
[root@mha ~]# sudo xtrabackup --copy-back --target-dir=/fullbak
# 原因:将已准备好的备份数据复制到 MySQL 数据目录。
# 6. 修改文件权限
[root@mha ~]# sudo chown -R mysql:mysql /var/lib/mysql
# 原因:恢复数据后,需要确保 MySQL 数据目录及其文件的权限正确。
# 7. 启动 MySQL 服务
[root@mha ~]# sudo systemctl start mysql
# 原因:完成上述步骤后,可以启动 MySQL 服务。
# 8. 验证恢复结果
[root@mha ~]# mysql -u root -p -e "SHOW DATABASES;"
# 原因:验证数据库和表是否已成功恢复。

备份完整性验证#

Terminal window
# 1. 准备备份
# 在验证之前,需要对备份进行准备操作,以应用事务日志,使备份数据处于一致状态。此步骤适用于全量备份和差异备份。
[root@mha ~]# xtrabackup --prepare --target-dir=/path/to/backup
# - `--prepare`:该参数用于对备份数据进行准备操作。
# - `--target-dir`:指定备份文件所在的目录。
# 2. 检查备份元数据文件
# 备份完成后,XtraBackup 会生成一个名为 `xtrabackup_info` 的元数据文件,该文件包含了备份的相关信息,如备份类型、开始时间、结束时间等。你可以查看这个文件来初步验证备份的基本信息是否正确。
[root@mha ~]# cat /path/to/backup/xtrabackup_info
# 查看输出内容,确认备份类型为差异备份(`incremental`),并且各项时间信息和其他元数据是否合理。
# 3. 检查备份文件的完整性
# 可以使用 `xtrabackup --stats` 命令来检查备份文件中的数据页和事务日志的完整性。
[root@mha ~]# xtrabackup --stats --target-dir=/path/to/backup
# - `--stats`:该参数用于显示备份文件的统计信息。
# - `--target-dir`:指定备份文件所在的目录。
# 如果备份文件完整,命令执行后会输出详细的统计信息,包括数据页的数量、事务日志的大小等。如果备份文件存在损坏,该命令可能会报错。
# 4. 模拟恢复操作
# 模拟恢复操作是验证备份完整性的最可靠方法。虽然不会真正覆盖现有的 MySQL 数据目录,但可以检查备份数据是否能够正确恢复。
# 停止 MySQL 服务(如果正在运行)
[root@mha ~]# sudo systemctl stop mysql
# 创建一个临时目录用于模拟恢复
[root@mha ~]# mkdir /tmp/restore-test
# 执行模拟恢复操作
[root@mha ~]# xtrabackup --copy-back --target-dir=/path/to/backup --datadir=/tmp/restore-test
# - `--copy-back`:将备份数据复制到指定的数据目录。
# - `--target-dir`:指定备份文件所在的目录。
# - `--datadir`:指定模拟恢复的数据目录。
# 如果模拟恢复过程中没有报错,说明备份文件可以正常恢复,完整性得到验证。恢复完成后,你可以查看临时目录中的文件是否与预期一致。
# 5. 清理临时目录
# 模拟恢复验证完成后,清理临时目录。
[root@mha ~]# rm -rf /tmp/restore-test
# 6. 启动 MySQL 服务
# 如果之前停止了 MySQL 服务,现在可以启动它。
[root@mha ~]# sudo systemctl start mysql
# 通过以上步骤,你可以全面验证 Percona XtraBackup 差异备份文件的完整性,确保在需要恢复数据时能够顺利进行。

备份方案案例#

以下是一个完整的 MySQL 备份与恢复方案,包含使用 mysqldump 进行定期全量备份、Percona XtraBackup 进行日常增量和差异备份,以及在数据丢失时的恢复方法。

1. 环境准备#

  • 安装 mysqldumpmysqldump 是 MySQL 自带的备份工具,通常在安装 MySQL 时会一并安装。
  • 安装 Percona XtraBackup:根据你的操作系统,按照 Percona 官方文档进行安装。例如,在 Ubuntu 上可以使用以下命令:
Terminal window
wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb
sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb
sudo apt-get update
sudo apt-get install percona-xtrabackup-80

2. 备份方案#

2.1 使用 mysqldump 进行定期全量备份#

mysqldump 适合进行全量备份,特别是对于较小的数据库。

脚本示例(full_backup.sh

#!/bin/bash
# 数据库连接信息
DB_USER="your_username"
DB_PASSWORD="your_password"
DB_NAME="your_database_name"
BACKUP_DIR="/path/to/backup"
# 创建备份目录
mkdir -p $BACKUP_DIR
# 生成备份文件名
BACKUP_FILE="$BACKUP_DIR/$(date +%Y%m%d)_full_backup.sql"
# 执行全量备份
mysqldump -u$DB_USER -p$DB_PASSWORD $DB_NAME > $BACKUP_FILE
# 检查备份是否成功
if [ $? -eq 0 ]; then
echo "Full backup completed successfully."
else
echo "Full backup failed."
fi

定时任务:使用 crontab 每周执行一次全量备份。

Terminal window
0 2 * * 0 /path/to/full_backup.sh

2.2 使用 Percona XtraBackup 进行日常增量和差异备份#

全量备份脚本(full_xtrabackup.sh

#!/bin/bash
# 数据库连接信息
DB_USER="your_username"
DB_PASSWORD="your_password"
BACKUP_DIR="/path/to/backup/xtrabackup"
# 创建备份目录
mkdir -p $BACKUP_DIR
# 生成备份文件名
FULL_BACKUP_DIR="$BACKUP_DIR/$(date +%Y%m%d)_full"
mkdir -p $FULL_BACKUP_DIR
# 执行全量备份
xtrabackup --user=$DB_USER --password=$DB_PASSWORD --backup --target-dir=$FULL_BACKUP_DIR
# 检查备份是否成功
if [ $? -eq 0 ]; then
echo "Full XtraBackup completed successfully."
else
echo "Full XtraBackup failed."
fi

增量备份脚本(incremental_backup.sh

#!/bin/bash
# 数据库连接信息
DB_USER="your_username"
DB_PASSWORD="your_password"
BACKUP_DIR="/path/to/backup/xtrabackup"
# 获取最新的全量备份目录
LAST_FULL_BACKUP=$(ls -d $BACKUP_DIR/*_full | tail -n 1)
# 生成增量备份目录
INCREMENTAL_BACKUP_DIR="$BACKUP_DIR/$(date +%Y%m%d)_incremental"
mkdir -p $INCREMENTAL_BACKUP_DIR
# 执行增量备份
xtrabackup --user=$DB_USER --password=$DB_PASSWORD --backup --target-dir=$INCREMENTAL_BACKUP_DIR --incremental-basedir=$LAST_FULL_BACKUP
# 检查备份是否成功
if [ $? -eq 0 ]; then
echo "Incremental backup completed successfully."
else
echo "Incremental backup failed."
fi

定时任务:每周执行一次全量备份,每天执行一次增量备份。

Terminal window
0 2 * * 0 /path/to/full_xtrabackup.sh
0 3 * * 1-6 /path/to/incremental_backup.sh

3. 恢复方案#

3.1 使用 mysqldump 恢复数据#

Terminal window
mysql -u your_username -p your_password your_database_name < /path/to/backup/20240101_full_backup.sql

3.2 使用 Percona XtraBackup 恢复数据#

步骤 1:准备全量备份

Terminal window
xtrabackup --prepare --target-dir=/path/to/backup/xtrabackup/20240101_full

步骤 2:应用增量备份

Terminal window
xtrabackup --prepare --target-dir=/path/to/backup/xtrabackup/20240101_full --incremental-dir=/path/to/backup/xtrabackup/20240102_incremental

步骤 3:停止 MySQL 服务

Terminal window
sudo systemctl stop mysql

步骤 4:恢复备份数据

Terminal window
sudo rm -rf /var/lib/mysql/*
sudo xtrabackup --copy-back --target-dir=/path/to/backup/xtrabackup/20240101_full
sudo chown -R mysql:mysql /var/lib/mysql

步骤 5:启动 MySQL 服务

Terminal window
sudo systemctl start mysql

六、作业#

1 选择题#

  1. 以下哪种备份方式能在备份时不锁表,从而不影响 MySQL 数据库的正常读写操作? B A. mysqldump 全量备份 B. PERCONA Xtrabackup 全量备份 C. mysqldump 增量备份 D. 以上都不能

  2. 使用 PERCONA Xtrabackup 进行增量备份时,基于的基础备份是?A A. 上一次的全量备份 B. 上一次的增量备份 C. 上一次的差异备份 D. 任意一次备份

  3. 当使用 mysqldump 备份数据库时,若要备份所有数据库,应使用以下哪个参数? A A. —all-databases B. —database-all C. —full-databases D. —every-database

  4. PERCONA Xtrabackup 的差异备份恢复时,依赖于?A A. 最新的全量备份和后续的差异备份 B. 最新的增量备份和后续的差异备份 C. 最早的全量备份和所有后续备份 D. 任意一次全量备份和差异备份

  5. 若要使用 PERCONA Xtrabackup 进行增量备份,需要记录上一次备份的什么信息? C A. 备份文件大小 B. 备份文件位置 C. 备份的 LSN(日志序列号) D. 备份的时间戳

2 简答题#

  1. 简述 mysqldump、PERCONA Xtrabackup 增量备份和差异备份的优缺点。
Terminal window
答:
mysqldump:
优点:灵活,可以针对单表或多表和单数据库或多数据进行备份还原
缺点:备份和恢复数据时会锁表,锁表期间无法对表做写访问。只适合备份数据量比较小的数据或在数据库服务器访问量少的时候备份。
PERCONA Xtrabackup 增量备份:
优点:备份速度快,占用空间小,因为每次只备份变化的数据。
缺点:恢复数据时,需要先恢复完整备份,然后按照时间顺序依次恢复所有的增量备份,直到指定的时间点。恢复过程复杂且耗时,如果中间任何一个备份损坏,可能导致整个恢复链失效。
PERCONA Xtrabackup 差异备份:
优点:恢复时只需要完整备份和最近一次的差异备份,恢复过程相对简单。
缺点:随着时间推移,差异备份的大小会越来越大,因为每次都要备份自完整备份以来的所有变化。备份时间可能会逐渐增加。
  1. 阐述在什么业务场景下适合使用 PERCONA Xtrabackup 的增量备份,什么场景适合使用差异备份。
Terminal window
答:
增量备份:
数据量大,备份窗口短,但对恢复时间要求不高的场景。
差异备份:
数据量变化不大,且希望恢复过程相对简单的场景。
  1. 说明在进行 MySQL 数据库恢复时,全量备份、增量备份和差异备份的恢复顺序及原因。 答: 全量备份恢复步骤:
Terminal window
# 停止 MySQL 服务。在恢复备份之前,需要停止正在运行的 MySQL 服务,以避免数据冲突。
[root@mha ~]# sudo systemctl stop mysql
# 清空 MySQL 数据目录。为了确保恢复的数据是完整的,需要清空 MySQL 数据目录中的现有数据。
[root@mha ~]# sudo rm -rf /var/lib/mysql/*
# 预处理备份数据。应用重做日志(redo log)到数据文件,将数据文件前滚到备份结束时的状态,使备份数据处于一致状态,可以用于恢复。
[root@mha ~]# sudo xtrabackup --prepare --target-dir=/path/to/backup
# 恢复备份数据。将备份数据复制到 MySQL 数据目录。
[root@mha ~]# sudo xtrabackup --copy-back --target-dir=/path/to/backup
# 修改文件权限。恢复数据后,需要确保 MySQL 数据目录及其文件的权限正确。
[root@mha ~]# sudo chown -R mysql:mysql /var/lib/mysql
# 启动 MySQL 服务。完成上述步骤后,可以启动 MySQL 服务。
[root@mha ~]# sudo systemctl start mysql
# 验证恢复结果。可以登录 MySQL 并检查数据库和表是否已成功恢复。
[root@mha ~]# mysql -u root -p
增量备份恢复步骤:
Terminal window
#准备恢复数据。使用 `--apply-log-only`只应用重做日志,不回滚为后续增量备份应用做准备。因为在增量备份中,基础备份必须保持事务状态,以便后续的增量备份能够正确应用。如果提前回滚了未提交事务,那么增量备份应用时可能会丢失一些事务信息。
[root@mha ~]# sudo xtrabackup --prepare --apply-log-only --target-dir=/fullbak
#合并增量数据,需要把所有的增量备份数据全部合并,不然会造成数据缺失
[root@mha ~]# sudo xtrabackup --prepare --apply-log-only --target-dir=/fullbak --incremental-dir=/new1
[root@mha ~]# sudo xtrabackup --prepare --apply-log-only --target-dir=/fullbak --incremental-dir=/new2
[root@mha ~]# sudo xtrabackup --prepare --apply-log-only --target-dir=/fullbak --incremental-dir=/new3
# 停止 MySQL 服务。在恢复备份之前,需要停止正在运行的 MySQL 服务,以避免数据冲突。
[root@mha ~]# sudo systemctl stop mysql
# 清空 MySQL 数据目录。为了确保恢复的数据是完整的,需要清空 MySQL 数据目录中的现有数据。
[root@mha ~]# sudo rm -rf /var/lib/mysql/*
# 最终准备预处理备份数据。应用重做日志(redo log)到数据文件,将数据文件前滚到备份结束时的状态,使备份数据处于一致状态,可以用于恢复。
[root@mha ~]# sudo xtrabackup --prepare --target-dir=/fullbak
# 恢复备份数据。将备份数据复制到 MySQL 数据目录。
[root@mha ~]# sudo xtrabackup --copy-back --target-dir=/fullbak
# 修改文件权限。恢复数据后,需要确保 MySQL 数据目录及其文件的权限正确。
[root@mha ~]# sudo chown -R mysql:mysql /var/lib/mysql
# 启动 MySQL 服务。完成上述步骤后,可以启动 MySQL 服务。
[root@mha ~]# sudo systemctl start mysql
# 验证恢复结果。可以登录 MySQL 并检查数据库和表是否已成功恢复。
[root@mha ~]# mysql -u root -p
差异备份恢复步骤:
Terminal window
#准备恢复数据。使用 `--apply-log-only`只应用重做日志,不回滚为后续增量备份应用做准备。因为在增量备份中,基础备份必须保持事务状态,以便后续的增量备份能够正确应用。如果提前回滚了未提交事务,那么增量备份应用时可能会丢失一些事务信息。
[root@mha ~]# sudo xtrabackup --prepare --apply-log-only --target-dir=/fullbak
#合并差异数据,只需要把全量数据和最后一次的差异数据合并,但暂不完成最终一致性
[root@mha ~]# sudo xtrabackup --prepare --target-dir=/fullbak --incremental-dir=/dir7
# 停止 MySQL 服务。在恢复备份之前,需要停止正在运行的 MySQL 服务,以避免数据冲突。
[root@mha ~]# sudo systemctl stop mysql
# 清空 MySQL 数据目录。为了确保恢复的数据是完整的,需要清空 MySQL 数据目录中的现有数据。
[root@mha ~]# sudo rm -rf /var/lib/mysql/*
# 最终准备预处理备份数据。应用重做日志(redo log)到数据文件,将数据文件前滚到备份结束时的状态,使备份数据处于一致状态,可以用于恢复。
[root@mha ~]# sudo xtrabackup --prepare --target-dir=/fullbak
# 恢复备份数据。将备份数据复制到 MySQL 数据目录。
[root@mha ~]# sudo xtrabackup --copy-back --target-dir=/fullbak
# 修改文件权限。恢复数据后,需要确保 MySQL 数据目录及其文件的权限正确。
[root@mha ~]# sudo chown -R mysql:mysql /var/lib/mysql
# 启动 MySQL 服务。完成上述步骤后,可以启动 MySQL 服务。
[root@mha ~]# sudo systemctl start mysql
# 验证恢复结果。可以登录 MySQL 并检查数据库和表是否已成功恢复。
[root@mha ~]# mysql -u root -p
  1. 比较 mysqldump 和 PERCONA Xtrabackup 在备份和恢复过程中对数据库性能的影响。
Terminal window
答:
mysqldump:
在备份和恢复数据时会通过锁表保证一致性,影响写操作,锁表期间无法对表做写访问
PERCONA Xtrabackup:
利用InnoDB的MVCC机制,实现热备份,几乎不影响业务

3 操作题#

  1. 请写出使用 mysqldump 对指定一个数据库进行全量备份,并将备份文件存储到“/backup/sales_full_backup.sql”的完整命令。
Terminal window
[root@mha ~]# mysqldump -uroot -p123 -B moershi > /backup/sales_full_backup.sql
mysqldump: [Warning] Using a password on the command line interface can be insecure.
[root@mha ~]# ls /backup
sales_full_backup.sql
  1. 假设已经有一个 PERCONA Xtrabackup 的全量备份,之后数据库有了新的数据更新,写出进行一次增量备份的操作步骤和相应命令。
Terminal window
[root@mha ~]# xtrabackup --host=127.0.0.1 --user=root --password=123 --backup --target-dir=/增量备份保存路径 --incremenntal-basedir=/全量备份保存路径 --datadir=/mysql数据路径
  1. 若数据库因磁盘故障丢失部分数据,现有一个全量备份和若干个 PERCONA Xtrabackup 的差异备份文件,请详细描述恢复数据库的操作过程和命令。
Terminal window
1.准备恢复数据,预处理只应用重做日志,不回滚为后续备份应用做准备。
[root@mha ~]# sudo xtrabackup --prepare --apply-log-only --target-dir=/全量备份数据
2.合并差异数据,只需要把一个全量备份数据和最后一次的差异备份数据合并,但暂不完成最终一致性
[root@mha ~]# sudo xtrabackup --prepare --target-dir=/全量备份数据 --incremental-dir=/差异备份数据
3.停止 MySQL 服务。在恢复备份之前,需要停止正在运行的 MySQL 服务,以避免数据冲突。
[root@mha ~]# sudo systemctl stop mysql
4.清空 MySQL 数据目录。为了确保恢复的数据是完整的,需要清空 MySQL 数据目录中的现有数据。
[root@mha ~]# sudo rm -rf /var/lib/mysql/*
5.最终准备预处理备份数据。应用重做日志(redo log)到数据文件,将数据文件前滚到备份结束时的状态,使备份数据处于一致状态,可以用于恢复。
[root@mha ~]# sudo xtrabackup --prepare --target-dir=/全量备份数据
6.恢复备份数据。将备份数据复制到 MySQL 数据目录。
[root@mha ~]# sudo xtrabackup --copy-back --target-dir=/全量备份数据
7.修改文件权限。恢复数据后,需要确保 MySQL 数据目录及其文件的权限正确。
[root@mha ~]# sudo chown -R mysql:mysql /var/lib/mysql
8.启动 MySQL 服务。完成上述步骤后,可以启动 MySQL 服务。
[root@mha ~]# sudo systemctl start mysql
9.验证恢复结果。可以登录 MySQL 并检查数据库和表是否已成功恢复。
[root@mha ~]# mysql -u root -p
  1. 使用 PERCONA Xtrabackup 进行差异备份时,如何验证备份文件的完整性?写出具体步骤和命令。
Terminal window
1. 准备备份
在验证之前,需要对备份进行准备操作,以应用事务日志,使备份数据处于一致状态。
[root@mha ~]# xtrabackup --prepare --target-dir=/path/to/backup
2. 检查备份元数据文件
备份完成后,XtraBackup 会生成一个名为 `xtrabackup_info` 的元数据文件,该文件包含了备份的相关信息,如备份类型、开始时间、结束时间等。可以查看这个文件来初步验证备份的基本信息是否正确。
[root@mha ~]# cat /path/to/backup/xtrabackup_info
查看输出内容,确认备份类型为差异备份(`incremental`),并且各项时间信息和其他元数据是否合理。
3. 检查备份文件的完整性
可以使用 `xtrabackup --stats` 命令来检查备份文件中的数据页和事务日志的完整性。
[root@mha ~]# xtrabackup --stats --target-dir=/path/to/backup
如果备份文件完整,命令执行后会输出详细的统计信息,包括数据页的数量、事务日志的大小等。如果备份文件存在损坏,该命令可能会报错。
  1. 请设计一个完整的 MySQL 备份与恢复方案,包括使用 mysqldump 进行定期全量备份、PERCONA Xtrabackup 进行日常增量和差异备份,并描述在数据丢失时如何利用这些备份进行恢复。
Terminal window
一。备份方案
1 使用 `crontab` `mysqldump` 进行定期全量备份
0 2 * * 0 /bin/mysqldump -uroot -p123 -A > /backup/sql/all_$(date +%Y-%m-%d_%H-%M-%S).sql
2 使用 `Percona XtraBackup` 进行日常增量和差异备份
全量备份脚本
#!/bin/bash
# 数据库连接信息
DB_USER="root"
DB_PASSWORD="123"
BACKUP_DIR="/fullbak"
# 创建备份目录
mkdir -p $BACKUP_DIR
# 生成备份文件名
FULL_BACKUP_DIR="$BACKUP_DIR/$(date +%Y%m%d)_full"
mkdir -p $FULL_BACKUP_DIR
# 执行全量备份
xtrabackup --host=127.0.0.1 --user=$DB_USER --password=$DB_PASSWORD --backup --target-dir=$FULL_BACKUP_DIR --datadir=/var/lib/mysql
# 检查备份是否成功
if [ $? -eq 0 ]; then
echo "Full XtraBackup completed successfully."
else
echo "Full XtraBackup failed."
fi
增量备份脚本
#!/bin/bash
# 数据库连接信息
DB_USER="root"
DB_PASSWORD="123"
BACKUP_DIR="/fullbak"
# 获取最新的全量备份目录
LAST_FULL_BACKUP=$(ls -d $BACKUP_DIR/*_full | tail -n 1)
# 生成增量备份目录
INCREMENTAL_BACKUP_DIR="$BACKUP_DIR/$(date +%Y%m%d)_incremental"
mkdir -p $INCREMENTAL_BACKUP_DIR
# 执行增量备份
xtrabackup --host=127.0.0.1 --user=$DB_USER --password=$DB_PASSWORD --backup --target-dir=$INCREMENTAL_BACKUP_DIR --incremental-basedir=$LAST_FULL_BACKUP --datadir=/var/lib/mysql
# 检查备份是否成功
if [ $? -eq 0 ]; then
echo "Incremental backup completed successfully."
else
echo "Incremental backup failed."
fi
定时任务:每周执行一次全量备份,每天执行一次增量备份。
0 2 * * 0 /全量备份脚本
0 3 * * 1-6 /增量备份脚本
二. 恢复方案
1 使用 `mysqldump` 恢复数据
mysql -uroot -p123 -A < /backup/sql/all_指定恢复时间版本.sql
2 使用 `Percona XtraBackup` 恢复数据
#准备恢复数据。
[root@mha ~]# sudo xtrabackup --prepare --apply-log-only --target-dir=/全量备份路径
#合并增量数据
[root@mha ~]# sudo xtrabackup --prepare --apply-log-only --target-dir=/全量备份路径 --incremental-dir=/增量备份路径1
[root@mha ~]# sudo xtrabackup --prepare --apply-log-only --target-dir=/全量备份路径 --incremental-dir=/增量备份路径2
[root@mha ~]# sudo xtrabackup --prepare --apply-log-only --target-dir=/全量备份路径 --incremental-dir=/增量备份路径3
# 停止 MySQL 服务。
[root@mha ~]# sudo systemctl stop mysql
# 清空 MySQL 数据目录。
[root@mha ~]# sudo rm -rf /var/lib/mysql/*
# 最终准备预处理备份数据。
[root@mha ~]# sudo xtrabackup --prepare --target-dir=/全量备份路径
# 恢复备份数据。
[root@mha ~]# sudo xtrabackup --copy-back --target-dir=/全量备份路径
# 修改文件权限。
[root@mha ~]# sudo chown -R mysql:mysql /var/lib/mysql
# 启动 MySQL 服务。
[root@mha ~]# sudo systemctl start mysql
# 验证恢复结果。
[root@mha ~]# mysql -u root -p

作业的详细检查#

1 选择题#

  • 第 1 题:答案正确。PERCONA Xtrabackup 全量备份利用 InnoDB 的 MVCC 机制实现热备份,备份时不锁表,不影响数据库正常读写操作;而 mysqldump 备份时会锁表。
  • 第 2 题:答案正确。PERCONA Xtrabackup 进行增量备份时,基于上一次的全量备份。
  • 第 3 题:答案正确。--all - databasesmysqldump 用于备份所有数据库的参数。
  • 第 4 题:答案正确。PERCONA Xtrabackup 的差异备份恢复时,依赖于最新的全量备份和后续的差异备份。
  • 第 5 题:答案错误。若要使用 PERCONA Xtrabackup 进行增量备份,需要记录上一次备份的 LSN(日志序列号),而不是备份文件位置。所以正确答案选 C。

2 简答题#

  • 第 1 题:回答准确,清晰阐述了 mysqldumpPERCONA Xtrabackup 增量备份和差异备份的优缺点。
  • 第 2 题:回答合理,增量备份适合数据量大、备份窗口短且对恢复时间要求不高的场景;差异备份适合数据量变化不大且希望恢复过程相对简单的场景。
  • 第 3 题
    • 回答内容整体正确,但存在一个小问题,在增量备份和差异备份准备恢复数据的注释中,提到“因为在增量备份中,基础备份必须保持事务状态,以便后续的增量备份能够正确应用”,这里应该是为了后续的增量或差异备份能够正确应用,表述不够严谨。
    • 另外,在代码中路径使用 /fullbak/new1 等应该是示例,实际操作需要替换为真实路径。
  • 第 4 题:回答正确,准确比较了 mysqldumpPERCONA Xtrabackup 在备份和恢复过程中对数据库性能的影响。

3 操作题#

  • 第 1 题
    • 命令基本正确,但需要注意的是,使用 -p 后面直接跟密码会有安全风险,实际操作中建议不直接写密码,而是在提示时输入。同时,-B 选项用于指定数据库,这里 moershi 应该是你要备份的数据库名,如果需要备份 sales 数据库,应该将 moershi 替换为 sales
  • 第 2 题
    • 命令存在拼写错误,--incremenntal - basefir 应该为 --incremental - basedir。正确的命令为:
Terminal window
[root@mha ~]# xtrabackup --host=127.0.0.1 --user=root --password=123 --backup --target-dir=/增量备份保存路径 --incremental-basedir=/全量备份保存路径 --datadir=/mysql数据路径
- 同样,路径需要替换为实际路径。
  • 第 3 题:回答正确,详细描述了使用全量备份和差异备份恢复数据库的操作过程和命令。
  • 第 4 题:回答正确,给出了验证 PERCONA Xtrabackup 差异备份文件完整性的具体步骤和命令。
  • 第 5 题
    • 备份方案:
      • 使用 crontabmysqldump 进行定期全量备份的命令基本正确,但密码使用方式存在安全风险,建议使用更安全的方式存储密码。
      • Percona XtraBackup 进行全量、增量备份脚本和定时任务设置思路正确,但路径需要替换为实际路径。
    • 恢复方案:
      • 使用 mysqldump 恢复数据的命令中,$(date +%Y - %m - %d_%H - %M - %S) 会获取当前时间,应该指定具体的备份文件时间,而不是当前时间。
      • 使用 Percona XtraBackup 恢复数据的步骤正确,但路径需要替换为实际路径。

总体来说,作业完成情况较好,但存在一些小错误和需要注意的安全问题,希望你能及时修改完善。

08:mysql之备份与恢复
https://fuwari.vercel.app/posts/数据库/08-mysql之备份与恢复/
作者
肥猫少杰
发布于
2026-06-03
许可协议
CC BY-NC-SA 4.0