【备份和恢复】Percona Xtrabackup
Percona Xtrabackup(简称PXB)是一个用于MySQL的开源热备份工具,通过拷贝服务器本地的数据文件进行备份。
注意:命令innobackupex和xtrabackup 的区别
特性 | innobackupex | xtrabackup |
---|---|---|
支持的存储引擎 | InnoDB、XtraDB、MyISAM | InnoDB 和 XtraDB |
操作级别 | xtrabackup的高级封装,使用方便 | 低级别操作,需要更复杂配置 |
适合版本 | v56、v57 | v80 |
安装包 | percona-xtrabackup-24-2.4.20-1.el7.x86_64.rpm | percona-xtrabackup-80-8.0.27-19.2.el7.x86_64.rpm |
主程序 | innobackupex、xtraback | xtrabackup |
1、PXB工作原理
01、备份InnoDB表
热备,不锁表
1、备份时,首先触发CKPT,将脏页刷写到磁盘,并记录一个LSN编号
2、拷贝InnoDB表相关的文件
3、将备份过程中产生的redo也备份,并记录LSN编号
4、将二进制日志、Position记录下来
5、恢复时:PXB模拟InnoDB存储引擎的CR过程,将数据和redo的LSN追平,然后进行一致性恢复,直接拷贝回MySQL目录即可
02、备份非InnoDB表
温备,短暂锁表,对业务有一定的影响
1、加全局读锁(FTWRL),而后触发刷写脏页,将已提交的数据页刷写到磁盘,并记录一个LSN编号;
2、拷贝非InnoDB表文件
3、拷贝数据完成后解锁
4、将二进制日志、Position记录下来
5、将所有备份文件统一存放在一个目录下
2、工具:innobackupex
01、安装innobackupex
# 【v56、57】
yum -y install percona-xtrabackup-24-2.4.20-1.el7.x86_64.rpm
【innobackex 常用选项】
--host # 数据库服务器IP
--port # 数据库服务端口
--socket # 套接字文件
--no-timestamp # 阻止自动创建时间戳的目录
--defaults-files # 指定其他配置文件,默认是/etc/my.cnf(使用时,必须放在所有参数最前面)
--incremental # 开启增备
--incremental-basedir # 基于哪个备份做增量
--incremental-dir # 恢复时,指定哪个备份整理到全备
--apply-log # 应用xtrabackup_logfile,模拟CR,重做(redo)已提交事务,回滚(undo)未提交事务
--redo-only # 只做(redo)已提交事务(模拟CR前滚,追平redo的LSN),不做undo回滚
--use-memory # 在准备阶段,提供内存以加速处理,默认100M
--compact # 压缩备份
--stream={tar|xbstream} # 对备份的数据流式化处理
--copy-back # 恢复备份至数据库服务器的数据目录
02、全备和恢复
# 1、全备命令
innobackupex --user=athos --password=123qwe --socket=/tmp/mysql.sock --no-timestamp /backup/mysql/pxb/full
# 2、恢复数据
# 1)整理全备文件
innobackupex --apply-log /backup/mysql/pxb/full # --apply-log手动模拟CR,重做redo,回滚undo
# 2)将备份恢复到MySQL数据目录
/etc/init.d/mysqld stop # 1)停数据库服务,必须是停止状态
mkdir -p /data/mysql/old # 创建目录用于存放数据目录下的文件
\cp -ra /data/mysql/data/* /data/mysql/old/ # 备份数据目录下文件(防止二次破坏)
rm -rf /data/mysql/data/* # 2)被恢复的目录必须是空的
innobackupex --copy-back /backup/mysql/pxb/full # 拷贝备份到数据目录
chown -R mysql.mysql /data/mysql/data # 修改数据权限
/etc/init.d/mysqld start # 启动服务
03、增备和恢复
增备:基于上次备份做备份,上次备份可能是全备或增备
# 1、全备命令
innobackupex --user=athos --password=123qwe --socket=/tmp/mysql.sock --no-timestamp /backup/mysql/pxb/full
# 2、增备命令
# 第1次增备:基于全备做第1次增备
innobackupex --user=athos --password=123qwe --socket=/tmp/mysql.sock --no-timestamp \
--incremental --incremental-basedir=/backup/mysql/pxb/full /backup/mysql/pxb/inc1
# 第2次增备:基于第1次增备做第2次增备
innobackupex --user=athos --password=123qwe --socket=/tmp/mysql.sock --no-timestamp \
--incremental --incremental-basedir=/backup/mysql/pxb/inc1 /backup/mysql/pxb/inc2
以此类推...
【恢复思路】
1)整理全备full
2)合并第1次增备inc1到全备full
3)合并第2次增备inc2到全备full
4)以此类推
5)最后再次整理全备full
6)将全备文件恢复到MySQL数据目录
# 3、恢复数据
# 1)整理全备full,只做redo,不做undo
innobackupex --apply-log --redo-only /backup/mysql/pxb/full
# --apply-log # 模拟CR,将redo和undo都做一次
# --read-noly # 只做redo,不做undo回滚;
【在整理全备、合并所有增备到全备(除了最后一次合并增备到全备、最后一次整理full),其他都需要加此参数。这样可以防止"last_lsn"值发生变化。】
# 2)合并第1次增备inc1到全备full
innobackupex --apply-log --redo-only --incremental-dir=/backup/mysql/pxb/inc1 /backup/mysql/pxb/full
# 3)合并第2次增备inc2到全备full
innobackupex --apply-log --incremental-dir=/backup/mysql/pxb/inc2 /backup/mysql/pxb/full
# 4)最后一次整理full
innobackupex --apply-log /backup/mysql/pxb/full
# 5)将备份恢复到MySQL数据目录
/etc/init.d/mysqld stop # 1)停数据库服务,必须是停止状态
mkdir -p /data/mysql/old # 创建目录用于存放数据目录下的文件
\cp -ra /data/mysql/data/* /data/mysql/old/ # 备份数据目录下文件(防止二次破坏)
rm -rf /data/mysql/data/* # 2)被恢复的目录必须是空的
innobackupex --copy-back /backup/mysql/pxb/full # 拷贝备份到数据目录
chown -R mysql.mysql /data/mysql/data # 修改数据权限
/etc/init.d/mysqld start # 启动服务
binlog截取部分省略...
04、差异备份和恢复
差异备份:每次备份都是基于上次全备做备份,备份上次全备以来发变化的数据
使用增备的命令备份
# 1、全备命令
innobackupex --user=athos --password=123qwe --socket=/tmp/mysql.sock --no-timestamp /backup/mysql/pxb/full
# 2、差异备份命令
innobackupex --user=athos --password=123qwe --socket=/tmp/mysql.sock --no-timestamp \
--incremental --incremental-basedir=/backup/mysql/pxb/full /backup/mysql/pxb/add1
# 3、恢复
# 1)整理全备full,只做redo,不做undo
innobackupex --apply-log --redo-only /backup/mysql/pxb/full
# 2)合并差异备份add1到全备full
innobackupex --apply-log --incremental-dir=/backup/mysql/pxb/full /backup/mysql/pxb/full
# 3)最后一次整理full
innobackupex --apply-log /backup/mysql/pxb/full
# 4)将备份恢复到MySQL数据目录
/etc/init.d/mysqld stop # 1)停数据库服务,必须是停止状态
mkdir -p /data/mysql/old # 创建目录用于存放数据目录下的文件
\cp -ra /data/mysql/data/* /data/mysql/old/ # 备份数据目录下文件(防止二次破坏)
rm -rf /data/mysql/data/* # 2)被恢复的目录必须是空的
innobackupex --copy-back /backup/mysql/pxb/full # 拷贝备份到数据目录
chown -R mysql.mysql /data/mysql/data # 修改数据权限
/etc/init.d/mysqld start # 启动服务
3、PXB备份产生的文件
01、xtrabackup_checkpoints
记录LSN号,用于衔接全备和增备,判断是否备份成功?
上一次备份的to_lsn位置,就是下一次备份的from_lsn
[root@db01 full]# cat xtrabackup_checkpoints
backup_type = full-backuped # 备份类型:全备
from_lsn = 0 # 全备的起始点为0
to_lsn = 290009666 # 备份的结束LSN
last_lsn = 291986857 # 备份完成时记录的最后一个LSN(通常与 to_lsn 值相近,但可能稍大,因为备份结束后数据库还在运行。)
compact = 0 # 是否使用压缩备份,0=未启用,1=启用
recover_binlog_info = 0 # 是否记录了恢复所需的二进制日志信息,0=未启用,1=启用
flushed_lsn = 291962248 # 这是已刷新到磁盘的最后一个LSN
02、xtrabackup_binlog_info
记录备份完成时刻的binlog和pos,可以用于截取binlog的起点。
[root@db01 full]# cat xtrabackup_binlog_info
mysql-bin.000001 85700808
4、工具:xtrabackup
对于v80版本,由于默认存储引擎为InnoDB,淘汰了MyISAM。所以备份工具innobackup遭到了废弃,也只能使用xtrabackup了。
01、安装xtrabackup
# 【v80】
yum -y install percona-xtrabackup-80-8.0.27-19.2.el7.x86_64.rpm
【常用选项】
--backup # 备份命令
--compress # 压缩
--decompress # 解压,需要安装单独程序进行解压(qpress)
--copy-back # 恢复备份
--target-dir # 指定备份目录
--incremental-dir # 指定增量备份
--prepare # 整理数据
02、全备和恢复
mkdir -p /backup/mysql/pxb/full
# 1、全备命令
xtrabackup --defaults-file=/etc/my.cnf --user=athos --password=123qwe --socket=/tmp/mysql.sock \
--backup --target-dir=/backup/mysql/pxb/full
# 2、恢复数据
# 1)整理数据
xtrabackup --prepare --target-dir=/backup/mysql/pxb/full
# 2)清理mysql数据目录
/etc/init.d/mysqld stop # 1)停数据库服务,必须是停止状态
mkdir -p /data/mysql/old # 创建目录用于存放数据目录下的文件
\cp -ra /data/mysql/data/* /data/mysql/old/ # 备份数据目录下文件(防止二次破坏)
rm -rf /data/mysql/data/* # 2)被恢复的目录必须是空的
# 3)恢复数据到MySQL数据目录
xtrabackup --defaults-file=/etc/my.cnf --user=athos --password=123qwe --copy-back --target-dir=/backup/mysql/pxb/full
# 4)修改权限、重启服务
chown -R mysql.mysql /data/mysql/data
/etc/init.d/mysqld start
02、增备和恢复
mkdir -p /backup/mysql/pxb/full
# 1、全备命令
xtrabackup --defaults-file=/etc/my.cnf --user=athos --password=123qwe --socket=/tmp/mysql.sock \
--backup --target-dir=/backup/mysql/pxb/full
# 2、增备命令
# 第1次增备:基于全备做第1次增备
xtrabackup --defaults-file=/etc/my.cnf --user=athos --password=123qwe --socket=/tmp/mysql.sock \
--backup --target-dir=/backup/mysql/pxb/inc1 --incremental-basedir=/backup/mysql/pxb/full
# 第1次增备:基于全备做第1次增备
xtrabackup --defaults-file=/etc/my.cnf --user=athos --password=123qwe --socket=/tmp/mysql.sock \
--backup --target-dir=/backup/mysql/pxb/inc2 --incremental-basedir=/backup/mysql/pxb/inc1
以此类推...
【恢复思路】
1)整理全备full
2)合并第1次增备inc1到全备full
3)合并第2次增备inc2到全备full
4)以此类推
5)将全备文件恢复到MySQL数据目录
6)重启服务
# 1、整理full
xtrabackup --prepare --apply-log-only --target-dir=/backup/mysql/pxb/full
# 2、整理合并第1次增备inc1到全备full
xtrabackup --prepare --apply-log-only --incremental-dir=/backup/mysql/pxb/inc1 --target-dir=/backup/mysql/pxb/full
# 3、整理合并第2次增备inc2到全备full
xtrabackup --prepare --incremental-dir=/backup/mysql/pxb/inc2 --target-dir=/backup/mysql/pxb/full
# 4、清理mysql数据目录
/etc/init.d/mysqld stop # 1)停数据库服务,必须是停止状态
mkdir -p /data/mysql/old # 创建目录用于存放数据目录下的文件
\cp -ra /data/mysql/data/* /data/mysql/old/ # 备份数据目录下文件(防止二次破坏)
rm -rf /data/mysql/data/* # 2)被恢复的目录必须是空的
# 5、恢复数据到MySQL数据目录
xtrabackup --defaults-file=/etc/my.cnf --user=athos --password=123qwe --copy-back --target-dir=/backup/mysql/pxb/full
# 6、修改权限、重启服务
chown -R mysql.mysql /data/mysql/data
/etc/init.d/mysqld start
03、差异备份和恢复
# 1、全备命令
xtrabackup --defaults-file=/etc/my.cnf --user=athos --password=123qwe --socket=/tmp/mysql.sock \
--backup --target-dir=/backup/mysql/pxb/full
# 2、差异备份命令
xtrabackup --defaults-file=/etc/my.cnf --user=athos --password=123qwe --socket=/tmp/mysql.sock \
--backup --target-dir=/backup/mysql/pxb/add1 --incremental-basedir=/backup/mysql/pxb/full
# 3、恢复命令
# 1)整理全备
xtrabackup --prepare --apply-log-only --target-dir=/backup/mysql/pxb/full
# 2)整理合并差异备份add1到全备full
xtrabackup --prepare --incremental-dir=/backup/mysql/pxb/add1 --target-dir=/backup/mysql/pxb/full
# 3)清理mysql数据目录
/etc/init.d/mysqld stop # 1)停数据库服务,必须是停止状态
mkdir -p /data/mysql/old # 创建目录用于存放数据目录下的文件
\cp -ra /data/mysql/data/* /data/mysql/old/ # 备份数据目录下文件(防止二次破坏)
rm -rf /data/mysql/data/* # 2)被恢复的目录必须是空的
# 4)恢复数据到MySQL数据目录
xtrabackup --defaults-file=/etc/my.cnf --user=athos --password=123qwe --copy-back --target-dir=/backup/mysql/pxb/full
# 5)修改权限、重启服务
chown -R mysql.mysql /data/mysql/data
/etc/init.d/mysqld start
备份和恢复案例:v57备份和恢复案例
# 背景:备份时间全部都是每天凌晨的02:00
2023-11-16 周天:全备
2023-11-17 周一:增备
2023-11-18 周二:增备
2023-11-19 周三:增备 上午10:30误删库
# 1)模拟初始数据:
create database db01;
use db01;
create table tb01 (id int, name varchar(20));
insert into tb01 values (1,'athos');
insert into tb01 values (2,'masiu');
# 2)周天 2023-11-16 全备
innobackupex --defauls-file=/etc/my.cnf --user=root --password=123qwe --port=3306 --socket=/tmp/mysql.sock --no-timestamp /data/backup/pxb/full_`date +%F`
# 模拟插入数据
insert into db01.tb01 values (3,'alice');
# 3)周一 2023-11-17 增备
innobackupex --incremental --user=root --password=123qwe --socket=/tmp/mysql.sock --no-timestamp --incremental-basedir=/data/backup/pxb/full_2023-11-16 /data/backup/pxb/inc1_`date +%F`
# 模拟插入数据
insert into db01.tb01 values (4,'bob');
# 4)周二 2023-11-18 增备
innobackupex --incremental --user=root --password=123qwe --socket=/tmp/mysql.sock --no-timestamp --incremental-basedir=/data/backup/pxb/inc1_2023-11-17 /data/backup/pxb/inc2_`date +%F`
# 模拟插入数据
insert into db01.tb01 values (5,'nike');
# 5)周三2023-11-19:增备
innobackupex --incremental --user=root --password=123qwe --port=3306 --socket=/tmp/mysql.sock --no-timestamp --incremental-basedir=/data/backup/pxb/inc2_2023-11-18 /data/backup/pxb/inc3_`date +%F`
# 模拟插入数据
insert into db01.tb01 values (6.'dany');
# 模拟删库
drop database db01;
## 恢复思路:
1)停业务,挂维护页。
2)整理恢复所有备份:全备 + 所有增备
3)截取binlog:
- 起点:最近一次增备中xtrabackup_binlog_info中的位置
- 终点:截止删库前的操作
4)恢复binlog
5)启服务,撤维护页。
处理步骤:
# 1)整理全备
innobackupex --apply-log --redo-only /data/backup/pxb/full_2023-11-16
# 2)合并增备到全备
innobackupex --apply-log --redo-only --incremental-dir=/data/backup/pxb/inc1_2023-11-17 /data/backup/pxb/full_2023-11-16
innobackupex --apply-log --redo-only --incremental-dir=/data/backup/pxb/inc2_2023-11-18 /data/backup/pxb/full_2023-11-16
innobackupex --apply-log --incremental-dir=/data/backup/pxb/inc3_2023-11-19 /data/backup/pxb/full_2023-11-16
# 3)最后一次整理全备
innobackupex --apply-log /data/backup/pxb/full_2023-11-16
# 4)恢复数据
cp -rf /data/backup/pxb/full_2023-11-16 /data/mysql/data/
chown -R mysql.mysql /data/mysql/data
# 5) 截取binlog
# 确定起点:
cat /data/backup/pxb/inc3_2023-11-19/xtrabackup_binlog_info
mysql-bin.000007 2639
# 确定终点:
mysqlbinlog /data/mysql3306/logs/mysql-bin.000007 | grep -a3 'drop database'
#231116 11:03:02 server id 1 end_log_pos 2959 CRC32 0xd3162bb2 Anonymous_GTID last_committed=12 sequence_number=13 rbr_only=no
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 2959
#231116 11:03:02 server id 1 end_log_pos 3051 CRC32 0x7ade3584 Query thread_id=17 exec_time=0 error_code=0
SET TIMESTAMP=1700150582/*!*/;
drop database db01
/*!*/;
# at 3051
#231116 11:32:05 server id 1 end_log_pos 3074 CRC32 0x3aa4a537 Stop
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# 截取binlog
mysqlbinlog --start-position=2639 --stop-position=2959 /data/mysql3306/logs/mysql-bin.000007 > /data/backup/pxb/bin.sql
# 导入数据
/etc/init.d/mysqld start
mysql -uroot -p
mysql> set sql_log_bin=0;
mysql> source /data/backup/pxb/bin.sql
mysql> set sql_log_bin=1;
# 检查数据,启业务
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,完整转载请注明来自 athos.lau