MySQL xtrabackup

物理备份

xtrabackup介绍

MySQL冷备、mysqldump、MySQL热拷贝都无法实现对数据库进行==增量备份==。在实际生产环境中增量备份是非常实用的,如果数据大于50G或100G,存储空间足够的情况下,可以每天进行完整备份,如果每天产生的数据量较大,需要定制数据备份策略。例如每周实用完整备份,周一到周六实用增量备份。而Percona-Xtrabackup就是为了实现增量备份而出现的一款主流备份工具,Xtrabackup有2个工具,分别是xtrabakup、innobakupe。

Xtrabackup是Percona公司的一款用于MySQL==在线物理热备==的备份工具,支持MySQL、Percona server和MariaDB,开源免费,是目前较为受欢迎的主流备份工具,是一个只能对innoDB和xtraDB存储引擎做数据备份的工具,不能备份MyISAM数据表,支持在线备份(备份时不影响数据读写),全量备份和增量备份,单库单表备份,是商业备份工具InnoDB Hotbackup的一个很好的替代品。

它能对InnoDB和XtraDB存储引擎的数据库非阻塞地备份(对于MyISAM的备份同样需要加表锁)。

> 非阻塞 -> 没有加锁

[XtraBackup](https://www.percona.com/software/mysql-database/percona-xtrabackup) 是 [Percona](https://www.percona.com/) 开源的免费数据库热备份软件,它能对InnoDB数据库和XtraDB存储引擎的数据库非阻塞地备份(对于MyISAM的备份同样需要加表锁);

mysqldump备份方式是采用的逻辑备份,其最大的缺陷是备份和恢复速度较慢,如果数据库大于50G,mysqldump备份就不太适合。

当前Xtrabackup存在两个版本:Xtrabackup 2.4.x与8.0.x,分别用于备份MySQL 5.x与MySQL 8.0.x 版本。

目前 Xtrabackup 活跃的大版本有三个:

Xtrabackup 2.4 适用于 MySQL 5.6 和 MySQL 5.7。

Xtrabackup 8.0 适用于 MySQL 8.0。

Xtrabackup 8.1 适用于 MySQL 8.1。

注意,三个版本不能混用,因为 MySQL 8.0 版本 redo log 和数据字典格式都发生了变化,可能会出现不兼容的情况。
优点:
1. 能够对InnoDB实现热备,无需暂停数据库
2. 能够对MySQL进行增量备份
3. 对MySQL备份能够实现流式压缩并传输给其他服务器,–stream参数实现
4. MySQL服务运行时能够在MySQL 服务器之间进行表的迁移
5. 能够很容易创建一个MySQL从服务器
6. 备份MySQL时不会增加服务器负担
7. 自动备份校验
8. 还原速度快
9. XtraBackup能够带InnoDB引擎创建的表实现热备,对MyISAM引擎实现温备

缺点:
1.只能对innodb表增量备份,myisam表增量备份时是全备
2.xtrabackup备份MyISAM表之前要对全库进行加READLOCK,阻塞写操作,若备份是在从库上进行的话会影响主从同步,造成延迟对InnoDB表备份不会阻塞读写。

xtrabackup备份原理

在InnoDB内部会维护一个redo日志文件,我们也可以叫做事务日志文件。

事务日志会存储每一个InnoDB表数据的记录修改。

当InnoDB启动时,InnoDB会检查数据文件和事务日志,并执行两个步骤:它应用(前滚)已经提交的事务日志到数据文件,并将修改过但没有提交的数据进行回滚操作。

使用xtrabackup进行还原,需要xtrabackup进行”备份”和”准备”:先将文件全部复制过来,再根据事务日志对部分操作进行回滚,如下描述:

xtrabackup的备份过程。

Xtrabackup在启动时会记住log sequence number(LSN),并且复制所有的数据文件。

复制过程需要一些时间,所以这期间如果数据文件有改动,那么将会使数据库处于一个不同的时间点。

所以,xtrabackup会运行一个后台进程,用于监视事务日志,并从事务日志复制最新的修改。

Xtrabackup持续地做这个操作,这些数据改动会写入xtrabackup_logfile文件。xtrabackup自启动开始,就不停的将事务日志中每个数据文件的修改都记录下来。

接下来是准备(prepare)过程。

在这个过程中,xtrabackup使用之前复制的事务日志,对各个数据文件执行灾难恢复(就像mysql刚启动时要做的一样)。当这个过程结束后,数据库就可以做恢复还原了。

详细过程如下

1. 调用xtrabackup对innodb表空间文件(这一瞬间的映像Time1)备份,而在这个innodb表备份期间数据库是不加锁的,外部可以继续往库里增减数据(这才能叫热备份)。而在Time1和Time2这两个时间点之间的改动由一个线程不断地扫innodb log获得(ChangeSet1),一旦发现redo中有新的日志写入,立刻将日志记入后台日志文件xtrabackup_log中
2. 锁所有库。
3. 以直接拷贝的方式备份frm,MYD,MYI,MRG,TRG,TRN,opt格式的文件。
4. 步骤3中的数据备份完毕时(Time2),停止扫innodb log的线程,把ChangeSet1的数据拷贝到备份中。
5. 解锁所有库。
6. 终止挂起,备份完毕。

---
以下是整个备份过程的简要流程图:

1. 启动 `xtrabackup_log` 进程:实时监控并记录 MySQL 的 redo 日志变化。
2. 物理复制 InnoDB 数据文件:将 InnoDB 数据文件和系统表空间文件复制到备份目录。
3. 执行 `FLUSH TABLES WITH READ LOCK`:锁定所有表,准备备份非 InnoDB 文件。
4. 物理复制非 InnoDB 文件:将 MyISAM 表的 `.frm`, `.myd`, `.myi` 文件复制到备份目录。
5. 记录二进制日志位置:保存当前二进制日志的位置信息。
6. 解锁表:释放全局锁,允许数据库恢复正常操作。
7. 停止 `xtrabackup_log` 进程:终止后台进程,完成备份。

MySQL xtrabackup_第1张图片

[redo log](https://zhuanlan.zhihu.com/p/408175328)

`MySQL`日志 主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。

其中,比较重要的还要属二进制日志`binlog`(归档日志)和事务日志`redo log`(重做日志)和`undo log`(回滚日志)。

`redo log`(重做日志)是`InnoDB`存储引擎独有的,它让`MySQL`拥有了崩溃恢复能力。

> Redo Log 是 InnoDB 存储引擎特有的日志,主要用于确保事务的持久性(ACID 属性中的 D),即在数据库发生崩溃后能够恢复未完成的事务。
>
> 当数据发生变化时(如插入、更新或删除操作),这些变化首先会被记录到 Redo Log 中,然后再异步地应用到实际的数据文件中。
>
> 在数据库重启时,InnoDB 可以通过 Redo Log 来重做那些已经提交但尚未写入磁盘的数据更改,从而保证数据的一致性和完整性。

img

`MySQL` 实例挂了或宕机了,重启时,`InnoDB`存储引擎会使用`redo log`恢复数据,保证数据的持久性与完整性。

MySQL xtrabackup_第2张图片

获取xtrabackup备份工具

> 2.4 -> 5.x
>
> 8.x -> mysql版本8.x对应

网站域名:http://www.percona.com

安装 XtraBackup

需要添加 Percona 的 YUM 仓库并安装 Percona XtraBackup。

1. 导入 Percona 的 GPG 密钥:

   ```bash
   sudo yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpm
   ```
2. 启用 Percona XtraBackup 80 仓库

   ```bash
   sudo percona-release setup ps80
   ```
3. 更新包列表并安装 Percona XtraBackup:
   ```bash
   sudo yum install epel-release
   sudo yum update
   sudo yum install percona-xtrabackup-80
   ```
xtrabackup全库备份与恢复

备份核心思路:

1、使用xtrabackup对数据库中的所有库进行全量备份,备份完成后,其不能立即进行数据恢复(数据不完整,缺少12:00~12:30这个过程中的数据)

2、预备阶段备份过程中产生的xtrabackup_log应用到全量备份集

3、模拟故障(删除数据)=> rm -rf data/*

4、动员运维工程师进行全库恢复

5、测试验证

第一步:准备数据

```powershell
create database db_it default charset=utf8;
use db_it;
create table t1(id int,name varchar(10)) engine=myisam;
insert into t1 values (1,'jack');
create table t2(id int,name varchar(10)) engine=innodb;
insert into t2 values (1,'rose');
```

第二步:专门准备一个数据库备份账号,开通相应权限
```powershell
创建备份用户admin,并授予相应权限
create USER 'admin'@'localhost' IDENTIFIED WITH mysql_native_password BY 'Root123.';
grant reload,process,lock tables,replication client,BACKUP_ADMIN,select on *.* to 'admin'@'localhost';
flush privileges;

说明:
在数据库中需要以下权限:
RELOAD和LOCKTABLES权限:为了执行FLUSH TABLES WITH READ LOCK
REPLICATION CLIENT权限:为了获取binary log位置
PROCESS权限:显示有关在服务器中执行的线程的信息(即有关会话执行的语句的信息),允许使用SHOW ENGINE
```

第三步:使用xtrabackup工具进行全库备份

```powershell
# xtrabackup --user=admin --password=Root123. --backup --target-dir=/full_xtrabackup
说明:备份目录默认会自动创建,也可以手动创建

IMPoRTANT:Please check that the backup run completes successfully.
		At the end of a successful backup run xtrabackup
		prints "completed OK!".
```

第四步:预备阶段,把备份这段时间内产生的日志整合到全量备份中 ==重要==

XtraBackup 在执行 `--backup` 操作时只是物理复制了 InnoDB 数据文件,这些数据文件在复制过程中可能处于不一致状态

(因为备份期间数据库仍在运行,有并发事务操作)。

为了使备份的数据文件恢复成一个一致性可用的状态,需要使用:
```powershell
xtrabackup --prepare --target-dir=/full_xtrabackup
```
这个过程也叫做 "apply the redo log",它的主要作用是:

- 将事务日志(Redo Log)中的更改应用到数据页上;
- 提交已完成的事务;
- 回滚未完成的事务;
- 让整个数据目录达到一个一致性状态。

第五步:模拟数据库故障
```powershell
systemctl stop mysqld && systemctl status mysqld

rm -rf /var/lib/mysql/*
```
第六步:快速的恢复数据库中的数据
```powershell
xtrabackup --copy-back --target-dir=/full_xtrabackup
```
第七步:恢复数据时,一定要记得更改/mysql_3306/data目录下的文件拥有者以及所属组权限,否则mysql无法启动


第八步:启动MySQL,测试其是否正常
```powershell
systemctl restart mysqld
```
xtrabackup增量备份与恢复

> 什么是增量?
>
> 增量一定要有一个前提,必须要先有一个全量

1.全量备份

2.把全量备份产生的日志整合到全量备份

3.进行数据的增删改操作

4.增量备份

5.把增量备份及增量备份产生的日志文件全部整合到全量备份中

6.模拟故障

7.数据恢复

全量备份
```powershell
xtrabackup --user=root --password=Root123. --backup --target-dir=/backup/full

不要执行
xtrabackup --prepare --apply-log-only --target-dir=/backup/full
```
> 使用 `--apply-log-only`:适合在你需要为后续增量备份做准备时使用。它不会执行最后一步的撤销操作(rollback of incomplete transactions),从而允许进一步的增量备份被合并进来。
>
> 
>
> 不使用 `--apply-log-only`:当你完成了所有增量备份的合并,并准备好要恢复数据库时使用。此时,XtraBackup 将完成所有的恢复步骤,包括回滚未完成的事务,使得备份成为一个完全一致性、可直接用于恢复的备份集。

修改数据

```powershell
# mysql -p
Enter password:123

insert into t1 values (2,'piol')
insert into t1 values (3,'mary')
```
增量备份

```powershell
xtrabackup --user=root --password=Root123. --backup --target-dir=/backup/inc1 --incremental-basedir=/backup/full
```
增量备份

```
xtrabackup --user=root --password=Root123. --backup --target-dir=/backup/inc2 --incremental-basedir=/backup/inc1
```
> 这次是相对于第一个增量备份做增量
```
/backup/
├── full/      ← 全量备份(时间点 T0)
├── inc1/      ← 第一次增量备份(T0 ~ T1)
└── inc2/      ← 第二次增量备份(T1 ~ T2)
```
 恢复全量备份
```
xtrabackup --prepare --target-dir=/backup/full
xtrabackup --copy-back --target-dir=/backup/full
```
恢复到全量 + 第一次增量
```
# 1. 准备全量
xtrabackup --prepare --apply-log-only --target-dir=/backup/full

# 2. 合并第一次增量
xtrabackup --prepare --apply-log-only --target-dir=/backup/full --incremental-dir=/backup/inc1

# 3. 最终准备
xtrabackup --prepare --target-dir=/backup/full

# 4. 恢复数据
xtrabackup --copy-back --target-dir=/backup/full
```
> 一旦执行合并操作,原全量备份将被修改,无法再单独恢复到全量备份状态(T0)
>
> 如果还想保留原始全量备份,需要在合并前做一个副本
>
> ```
> cp -r /backup/full /backup/full_backup_T0
> ```
>
> | 阶段      | 操作                                                      | 是否影响原全量  |
> | --------- | --------------------------------------------------------- | --------- |
> | 准备全量  | `xtrabackup --prepare --apply-log-only --target-dir=full` | ❌ 不影响 |
> | 合并 inc1 | `--incremental-dir=inc1` 到 full                          |✅ 修改full| 
> | 合并 inc2 | `--incremental-dir=inc2` 到 full                          |✅ 继续full|

恢复到全量 + 第一次 + 第二次增量

```
# 1. 准备全量备份
xtrabackup --prepare --apply-log-only --target-dir=/backup/full

# 2. 合并第一个增量备份 inc1
xtrabackup --prepare --apply-log-only --target-dir=/backup/full --incremental-dir=/backup/inc1

# 3. 合并第二个增量备份 inc2
xtrabackup --prepare --apply-log-only --target-dir=/backup/full --incremental-dir=/backup/inc2

# 4. 最终准备(不再加 apply-log-only)
xtrabackup --prepare --target-dir=/backup/full

# 5. 恢复数据到数据库目录
xtrabackup --copy-back --target-dir=/backup/full
```

你可能感兴趣的:(mysql,数据库)