使用Percona XtraBackup备份Mysql数据
使用Percona XtraBackup备份Mysql数据
如下实验都是在Ubuntu 22.04 环境验证,Mysql版本是8.3.0,关于Mysql的安装请参考官方文档安装教程, Percona XtraBackup版本也是8.3。
Percona XtraBackup的安装
1、下载DEB安装包
wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb
2、安装依赖
apt-get install curl
3、安装Percona XtraBackup并验证
# 安装Percona仓库的配置包,在系统中添加Percona的软件源
dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb
# 更新了本地的包索引,它会从所有配置的仓库(包括刚刚添加的Percona仓库)中获取最新的软件包列表和版本信息
apt-get update
# 启用Percona的工具仓库
percona-release enable-only tools release
# 更新包索引
apt-get update
# 安装Percona XtraBackup
apt-get install percona-xtrabackup-83
# 验证xtrabackup
xtrabackup --version
安装成功后结果如下
xtrabackup version 8.3.0-1 based on MySQL server 8.3.0 Linux (x86_64) (revision id: 3e4e7ce9)
创建备份用户并授权
在安装并启动Mysql后,查看Mysql的错误日志,会有如下一条信息
2024-06-09T05:26:43.245586Z 0 [System] [MY-010931] [Server] /usr/local/mysql/bin/mysqld: ready for connections. Version: '8.3.0' socket: '/tmp/mysql.sock' port: 3306 MySQL Community Server - GPL.
其中的 /tmp/mysql.sock
是本地进程通信的套接字,后面配置XtraBackup与Mysql通信时需要用到。
# 创建用户备份数据的用户 backup_user,密码为forbackuppwd
CREATE USER 'backup_user'@'localhost' IDENTIFIED BY 'forbackuppwd';
# 授予备份用户权限
GRANT RELOAD, LOCK TABLES, PROCESS, REPLICATION CLIENT ON *.* TO 'backup_user'@'localhost';
GRANT SELECT ON `performance_schema`.* TO 'backup_user'@'localhost';
GRANT BACKUP_ADMIN ON *.* TO 'backup_user'@'localhost';
# 刷新权限
FLUSH PRIVILEGES;
配置 my.cnf,默认把my.cnf配置放在Mysql安装根目录下面,如:/usr/local/mysql/my.cnf
[client]
user=backup_user
password=forbackuppwd
socket=/tmp/mysql.sock
创建XtraBackup my.cnf软链接
cd /etc/mysql
ln -s /usr/local/mysql/my.cnf /etc/mysql/my.cnf
备份方式
全量备份
xtrabackup --backup --target-dir=/usr/local/mysql/backups/
输出结果如下
2024-06-09T14:23:03.020208+08:00 0 [Note] [MY-011825] [Xtrabackup] recognized server arguments: --server-id=1
2024-06-09T14:23:03.020326+08:00 0 [Note] [MY-011825] [Xtrabackup] recognized client arguments: --user=backup_user --password=* --socket=/tmp/mysql.sock --backup=1 --target-dir=/usr/local/mysql/backups/
xtrabackup version 8.3.0-1 based on MySQL server 8.3.0 Linux (x86_64) (revision id: 3e4e7ce9)
240609 14:23:03 version_check Connecting to MySQL server with DSN 'dbi:mysql:;mysql_read_default_group=xtrabackup;mysql_socket=/tmp/mysql.sock' as 'backup_user' (using password: YES).
240609 14:23:03 version_check Connected to MySQL server
240609 14:23:03 version_check Executing a version check against the server...
240609 14:23:03 version_check Done.
2024-06-09T14:23:03.082083+08:00 0 [Note] [MY-011825] [Xtrabackup] Connecting to MySQL server host: localhost, user: backup_user, password: set, port: not set, socket: /tmp/mysql.sock
2024-06-09T14:23:03.086630+08:00 0 [Note] [MY-011825] [Xtrabackup] Using server version 8.3.0
2024-06-09T14:23:03.088321+08:00 0 [Note] [MY-011825] [Xtrabackup] Executing LOCK INSTANCE FOR BACKUP ...
2024-06-09T14:23:03.089890+08:00 0 [Note] [MY-011825] [Xtrabackup] uses posix_fadvise().
2024-06-09T14:23:03.089940+08:00 0 [Note] [MY-011825] [Xtrabackup] cd to /usr/local/mysql/data/
2024-06-09T14:23:03.089948+08:00 0 [Note] [MY-011825] [Xtrabackup] open files limit requested 0, set to 1024
2024-06-09T14:23:03.101682+08:00 0 [Note] [MY-011825] [Xtrabackup] using the following InnoDB configuration:
2024-06-09T14:23:03.101762+08:00 0 [Note] [MY-011825] [Xtrabackup] innodb_data_home_dir = .
2024-06-09T14:23:03.101767+08:00 0 [Note] [MY-011825] [Xtrabackup] innodb_data_file_path = ibdata1:12M:autoextend
2024-06-09T14:23:03.101783+08:00 0 [Note] [MY-011825] [Xtrabackup] innodb_log_group_home_dir = ./
2024-06-09T14:23:03.101786+08:00 0 [Note] [MY-011825] [Xtrabackup] innodb_log_files_in_group = 2
2024-06-09T14:23:03.101796+08:00 0 [Note] [MY-011825] [Xtrabackup] innodb_log_file_size = 50331648
2024-06-09T14:23:03.110629+08:00 0 [Note] [MY-011825] [Xtrabackup] inititialize_service_handles suceeded
2024-06-09T14:23:03.198639+08:00 0 [Note] [MY-011825] [Xtrabackup] Connecting to MySQL server host: localhost, user: backup_user, password: set, port: not set, socket: /tmp/mysql.sock
2024-06-09T14:23:03.201752+08:00 0 [Note] [MY-011825] [Xtrabackup] Redo Log Archiving is not set up.
2024-06-09T14:23:03.314887+08:00 0 [Note] [MY-012953] [InnoDB] Disabling background ibuf IO read threads.
2024-06-09T14:23:03.317049+08:00 1 [Note] [MY-011825] [Xtrabackup] >> log scanned up to (20760599)
2024-06-09T14:23:03.524105+08:00 0 [Note] [MY-011825] [Xtrabackup] Generating a list of tablespaces
2024-06-09T14:23:03.524179+08:00 0 [Note] [MY-012204] [InnoDB] Scanning './'
2024-06-09T14:23:03.524662+08:00 0 [Note] [MY-012208] [InnoDB] Completed space ID check of 2 files.
2024-06-09T14:23:03.525162+08:00 0 [Warning] [MY-012091] [InnoDB] Allocated tablespace ID 2 for demo/demo, old maximum was 0
2024-06-09T14:23:03.525682+08:00 0 [Note] [MY-013252] [InnoDB] Using undo tablespace './undo_001'.
2024-06-09T14:23:03.526065+08:00 0 [Note] [MY-013252] [InnoDB] Using undo tablespace './undo_002'.
2024-06-09T14:23:03.526535+08:00 0 [Note] [MY-012910] [InnoDB] Opened 2 existing undo tablespaces.
2024-06-09T14:23:03.527079+08:00 2 [Note] [MY-011825] [Xtrabackup] Copying ./ibdata1 to /usr/local/mysql/backups/ibdata1
2024-06-09T14:23:03.578295+08:00 2 [Note] [MY-011825] [Xtrabackup] Done: Copying ./ibdata1 to /usr/local/mysql/backups/ibdata1
2024-06-09T14:23:03.583245+08:00 2 [Note] [MY-011825] [Xtrabackup] Copying ./sys/sys_config.ibd to /usr/local/mysql/backups/sys/sys_config.ibd
2024-06-09T14:23:03.583563+08:00 2 [Note] [MY-011825] [Xtrabackup] Done: Copying ./sys/sys_config.ibd to /usr/local/mysql/backups/sys/sys_config.ibd
2024-06-09T14:23:03.586156+08:00 2 [Note] [MY-011825] [Xtrabackup] Copying ./demo/demo.ibd to /usr/local/mysql/backups/demo/demo.ibd
2024-06-09T14:23:03.586768+08:00 2 [Note] [MY-011825] [Xtrabackup] Done: Copying ./demo/demo.ibd to /usr/local/mysql/backups/demo/demo.ibd
......
2024-06-09T14:23:04.981903+08:00 0 [Note] [MY-011825] [Xtrabackup] Backup created in directory '/usr/local/mysql/backups/'
2024-06-09T14:23:04.981960+08:00 0 [Note] [MY-011825] [Xtrabackup] MySQL binlog position: filename 'binlog.000010', position '158'
2024-06-09T14:23:04.981994+08:00 0 [Note] [MY-011825] [Xtrabackup] Writing /usr/local/mysql/backups/backup-my.cnf
2024-06-09T14:23:04.982062+08:00 0 [Note] [MY-011825] [Xtrabackup] Done: Writing file /usr/local/mysql/backups/backup-my.cnf
2024-06-09T14:23:04.984370+08:00 0 [Note] [MY-011825] [Xtrabackup] Writing /usr/local/mysql/backups/xtrabackup_info
2024-06-09T14:23:04.984599+08:00 0 [Note] [MY-011825] [Xtrabackup] Done: Writing file /usr/local/mysql/backups/xtrabackup_info
2024-06-09T14:23:05.989384+08:00 0 [Note] [MY-011825] [Xtrabackup] Transaction log of lsn (20760599) to (20760599) was copied.
2024-06-09T14:23:06.095130+08:00 0 [Note] [MY-011825] [Xtrabackup] completed OK!
备份结果
root@ubuntu-20:/usr/local/mysql# ll /usr/local/mysql/backups/
total 70716
drwxr-x--- 6 root root 4096 6月 9 14:23 ./
drwxr-xr-x 12 root root 4096 6月 9 14:23 ../
-rw-r----- 1 root root 447 6月 9 14:23 backup-my.cnf
-rw-r----- 1 root root 158 6月 9 14:23 binlog.000010
-rw-r----- 1 root root 16 6月 9 14:23 binlog.index
drwxr-x--- 2 root root 4096 6月 9 14:23 demo/
-rw-r----- 1 root root 3453 6月 9 14:23 ib_buffer_pool
-rw-r----- 1 root root 12582912 6月 9 14:23 ibdata1
drwxr-x--- 2 root root 4096 6月 9 14:23 mysql/
-rw-r----- 1 root root 26214400 6月 9 14:23 mysql.ibd
drwxr-x--- 2 root root 4096 6月 9 14:23 performance_schema/
drwxr-x--- 2 root root 4096 6月 9 14:23 sys/
-rw-r----- 1 root root 16777216 6月 9 14:23 undo_001
-rw-r----- 1 root root 16777216 6月 9 14:23 undo_002
-rw-r----- 1 root root 18 6月 9 14:23 xtrabackup_binlog_info
-rw-r----- 1 root root 134 6月 9 14:23 xtrabackup_checkpoints
-rw-r----- 1 root root 504 6月 9 14:23 xtrabackup_info
-rw-r----- 1 root root 2560 6月 9 14:23 xtrabackup_logfile
-rw-r----- 1 root root 39 6月 9 14:23 xtrabackup_tablespaces
执行Prepare动作
xtrabackup --prepare --target-dir=/usr/local/mysql/backups/
为什么需要做一步呢?因为在上一步的备份过程中,XtraBackup在复制数据文件和日志文件过程中,还有新的事务在执行,这些事务信息被写入了redo log,需要在Prepare阶段去执行这些redo log,让数据和日志达到一致。
增量备份
进行增量备份时,每次都以一次全量备份开始,使用命令如下
xtrabackup --backup --target-dir=/usr/local/mysql/backups/base
然后再进行增量备份,第一次增量备份可以执行如下命令
xtrabackup --backup --target-dir=/usr/local/mysql/backups/inc1 --incremental-basedir=/usr/local/mysql/backups/base
然后第二次增量备份可以执行如下命令
xtrabackup --backup --target-dir=/usr/local/mysql/backups/inc2 --incremental-basedir=/usr/local/mysql/backups/inc1
后面每一次都依次类推
下一步就是Prepare Backup阶段,前面说过,这一阶段,主要是应用在copy数据文件过程中新产生的事务日志,以此来保证数据文件和日志文件的一致性,在全量备份阶段,Prepare Backup 是应用已提交事务和回滚未提交的事务,但是在增量备份阶段,因为有可能事务在增量备份阶段一还没提交,但是到了增量备份阶段二才提交,因此对于增量备份来说,Prepare Backup阶段不能执行回滚事务,只有最后一次增量备份的恢复才需要执行
首先执行Prepare Full Backup
xtrabackup --prepare --apply-log-only --target-dir=/data/backups/base
然后执行第一次增量备份Prepare
xtrabackup --prepare --apply-log-only --target-dir=/data/backups/base --incremental-dir=/data/backups/inc1
再执行最后一次增量备份Prepare
xtrabackup --prepare --target-dir=/data/backups/base incremental-dir=/data/backups/inc2
注意:最后一次增量备份的Prepare 需要执行回滚事务日志。
压缩备份
创建压缩备份之前需要先安装一下Percona压缩算法插件
sudo percona-release enable tools
sudo apt update
sudo apt install zstd
然后执行压缩备份
xtrabackup --backup --compress --target-dir=/usr/local/mysql/backups/
执行完以后我们可以看一下备份目录的文件结构是什么样的,可以看到都是zst格式的压缩文件。
同样的,压缩备份也需要执行Prepare Backup阶段来保证数据和日志的一致性。但是在执行Prepare阶段之前,首先需要解压数据
xtrabackup --decompress --target-dir=/usr/local/mysql/backups/
解压完以后,目录中的文件长这样
然后再执行Prepare阶段
xtrabackup --prepare --target-dir=/usr/local/mysql/backups/
至此,压缩备份就结束了,后面就是根据备份数据如何恢复数据库的流程了。
从备份中恢复
在从备份数据中恢复之前,需要停掉Mysql进程,且保证Mysql 的数据保存目录是一个空目录。
如何查看Mysql数据保存目录呢?使用Mysql客户端登录以后执行如下语句
SHOW VARIABLES LIKE 'datadir';
xtrabackup --copy-back --target-dir=/usr/local/mysql/backups/ --datadir=/usr/local/mysql/data/
此处需要注意,如果在执行上面恢复语句的用户是与运行Mysql用户,则需要给Mysql运行用户赋予目录权限
chown -R mysql:mysql /usr/local/mysql/data/
然后重新启动Mysql实例
# 不同的Mysql安装方式可能Mysql实例启动方式不同
systemctl start mysql.service
备份策略
上面讲了全量备份、增量备份还有压缩备份,那么在我们项目中如何高效的使用它们呢?备份策略绝对不是固定的,因为它还受数据库数据大小、数据库服务器资源以及备份数据完整性要求等因素的影响。
但是对于大部分项目来说,数据库备份我们需要注意下面的这些问题
数据库备份需要注意的问题
1. 数据完整性和一致性
确保备份的数据是完整和一致的,即在备份过程中捕获所有必要的数据,并且数据在恢复后与备份时的状态一致。这包括:
- 捕获所有事务:确保在备份过程中所有已提交的事务都被捕获,并且未提交的事务在恢复时被正确处理。
- 一致性检查:在备份和恢复过程中进行一致性检查,确保数据文件和日志文件的一致性。
2. 数据安全性
保护备份数据免受未授权访问和数据泄露。这可以通过以下措施实现:
- 加密:对备份数据进行加密,确保即使备份文件被盗取,也无法轻易访问其中的数据。
- 访问控制:限制备份和恢复操作的权限,只有授权用户才能执行这些操作。
3. 数据可用性
确保在发生数据丢失或损坏时,可以快速有效地恢复数据,保证业务的连续性。这包括:
- 快速恢复:优化备份和恢复流程,确保在最短时间内恢复数据,减少业务中断时间。
- 多重备份策略:结合全量备份、增量备份和差异备份,确保在不同情况下都能找到合适的备份进行恢复。
4. 备份效率
在保证数据完整性和安全性的前提下,提高备份操作的效率,减少对系统性能的影响。这包括:
- 增量和差异备份:减少每次备份的数据量,提高备份速度,减少存储空间占用。
- 压缩备份:对备份数据进行压缩,进一步减少存储空间占用和传输时间。
5. 备份管理和监控
有效管理和监控备份过程,确保备份任务按计划执行,并及时发现和处理备份过程中出现的问题。这包括:
- 自动化备份:使用自动化工具和脚本定期执行备份任务,减少人为错误。
- 监控和报警:实时监控备份任务的执行情况,并在出现故障时发送报警通知,确保问题及时处理。
- 备份日志:记录备份和恢复操作的详细日志,便于审计和问题排查。
6. 备份存储和保留策略
合理规划备份数据的存储位置和保留期限,确保备份数据在需要时可用,并避免不必要的存储成本。这包括:
- 异地备份:将备份数据存储在异地,防止本地灾难(如火灾、地震等)导致备份数据和原始数据同时丢失。
- 备份保留策略:根据数据的重要性和恢复需求,制定备份数据的保留策略,定期清理过期的备份数据,释放存储空间。
7. 恢复测试
定期进行备份数据的恢复测试,确保备份数据在需要时能够成功恢复。这包括:
- 恢复演练:模拟实际的恢复场景,验证备份数据的可用性和恢复流程的有效性。
- 恢复时间目标(RTO):评估和优化恢复时间,确保在业务中断后能够在可接受的时间内恢复数据和服务。
Percona XtraBackup 的工作原理
通过前面我们知道, Percona XtraBackup的数据备份阶段分为两步,第一步是复制数据文件和日志文件,第二步是应用未执行的日志。
对于第一步来说, Percona XtraBackup过程如下:
- 启动长事务:
- XtraBackup 启动一个长事务来创建一个一致性快照。这确保在备份过程中捕获的数据文件是一致的。
- 记录初始 LSN:
- 记录一个初始 LSN,作为备份的一致性起点。
- 复制数据文件:
- XtraBackup 逐个复制 InnoDB 的数据文件(表空间文件)。这个过程中,新的事务可能会开始并提交。
- 为确保复制过程中数据文件的一致性,XtraBackup 持续记录数据文件的 LSN。
- 持续复制 redo log:
- 在数据文件复制过程中,XtraBackup 持续复制 redo log,捕获所有在备份期间的新事务。
- Redo log 的复制确保了在备份过程中所有对数据库的修改都被捕获。
- 判断数据文件复制完成:
- 当所有数据文件都被完整复制后,XtraBackup 会进入一个等待状态,等待 redo log 中的记录达到一致性点。
- 记录最终一致性点(Checkpoint LSN):
- XtraBackup 通过检查 redo log 中的 LSN,判断是否所有在数据文件复制过程中提交的事务都已被捕获。
- 当确认所有事务都被捕获后,记录一个最终一致性点(Checkpoint LSN)。
- 停止数据文件复制:
- 当达到最终一致性点后,XtraBackup 停止数据文件的复制,同时停止捕获 redo log。
对于第二步来说,就比较简单了
应用 redo log:
- 重做(replay)所有已提交的事务:在备份过程中捕获的 redo log 会被应用到数据文件中,确保所有已提交的事务都被重做。
- 确保数据一致性:通过应用 redo log,XtraBackup 确保数据文件中的数据与备份时数据库的实际状态一致。
应用 undo log:
- 回滚未完成的事务:在备份过程中,可能存在一些未完成的事务,这些事务需要通过 undo log 回滚。XtraBackup 会应用 undo log,回滚这些未完成的事务,确保备份数据的一致性。
- 保证数据一致性:通过回滚未完成的事务,确保所有事务都处于一致的状态。
参考资料
《高性能Mysql第四版》
转载自:https://juejin.cn/post/7378014138137854003