当前位置: 首页 > 工具软件 > XtraBackup > 使用案例 >

Xtrabackup备份恢复

哈烨熠
2023-12-01
1、安装xtrabackup工具
以下测试安装xtrabackup备份恢复工具的二进制包,进行测试。安装的路径为mysql安装路径,本次测试mysql的安装路径为:/usr/local/mysql。
tar -xzf percona-xtraback-2.0.0-x86-64.tar.gz
cp percona-xtrabackup-2.0.0/bin/* /usr/local/mysql/bin

2、创建备份用户
建备份用户backup@localhost,xtraback只能用于本地操作,故只授权本地操作。
GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO backup@localhost;

3、声明PATH环境变量
为xtrabackup备份恢复工具添加到PATH路径中。
export PATH=$PATH:/usr/local/mysql/bin

4、创建测试库
创建测试库backup_test,测试表test。
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'create database backup_test;'
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'create table backup_test.test (id int);'
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'insert into backup_test.test values(1),(2),(3),(4),(5);'

mysql> select * from test;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    5 |
+------+
5 rows in set (0.00 sec)

############################################
测试innodb
一:全备份测试
全备份测试主要通过测试以下几个场景,对数据备份和恢复进行验证。

1:备份全库,恢复进行测试。
进行全库备份:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf /backup/data

关闭数据库服务:
kill -9 $(ps -ef|grep "mysql"|gawk '$0 !~/grep/ {print $2}' |tr -s '\n' ' ')

删除当前数据文件:
rm -rf /mysql/data/*

恢复日志文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --apply-log /backup/data/2016-08-23_01-45-53

恢复数据文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --copy-back /backup/data/2016-08-23_01-45-53

数据验证:
chown -R mysql:mysql /mysql
mysqld_safe --defaults-file=/etc/my.cnf 
mysql -uroot --password=123456 -S/usr/local/mysql/mysql.sock -e'select * from backup_test.test;'
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    5 |
+------+
测试结果:
经验证,备份恢复正确。

****************************************************
2:修改表结构,备份全库,恢复进行测试
修改数据库表结构:
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e 'alter table backup_test.test add name varchar(20) default "null";'
mysql -uroot --password=123456 -S/usr/local/mysql/mysql.sock -e'select * from backup_test.test;'
+------+------+
| id   | name |
+------+------+
|    1 | null |
|    2 | null |
|    3 | null |
|    4 | null |
|    5 | null |
+------+------+

进行全库备份:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf /backup/data

关闭数据库服务:
kill -9 $(ps -ef|grep "mysql"|gawk '$0 !~/grep/ {print $2}' |tr -s '\n' ' ')

删除当前数据文件和日志文件:
rm -rf /mysql/data/*
rm -rf /mysql/logs/*

恢复日志文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --apply-log /backup/data/2016-08-23_08-24-38

恢复数据文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --copy-back /backup/data/2016-08-23_08-24-38

数据验证:
chown -R mysql:mysql /mysql
mysqld_safe --defaults-file=/etc/my.cnf &
mysql -uroot --password=123456 -S/usr/local/mysql/mysql.sock -e'select * from backup_test.test;'
+------+------+
| id   | name |
+------+------+
|    1 | null |
|    2 | null |
|    3 | null |
|    4 | null |
|    5 | null |
+------+------+
测试结果:
经验证,备份恢复正确。

**********************************************************
3:备份某个库,恢复测试
备份backup_test库
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --database=backup_test /backup/data

关闭数据库服务:
kill -9 $(ps -ef|grep "mysql"|gawk '$0 !~/grep/ {print $2}' |tr -s '\n' ' ')

修改当前数据文件:
mv /mysql/data /mysql/databak
mv /mysql/logs /mysql/logsbak
mkdir /mysql/data
mkdir /mysql/logs

恢复日志文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --apply-log --database=backup_test  /backup/data/2016-08-23_13-34-43

恢复数据文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --copy-back --database=backup_test /backup/data/2016-08-23_13-34-43
cp /mysql/databak/* /mysql/data                                            (仅拷贝不在data中的文件,注意相关文件夹下的文件不同,以备份出来的为准)

数据验证:
chown -R mysql:mysql /mysql
mysqld_safe --defaults-file=/etc/my.cnf &
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'select * from backup_test.test;'
+------+------+
| id   | name |
+------+------+
|    1 | null |
|    2 | null |
|    3 | null |
|    4 | null |
|    5 | null |
+------+------+
测试结果:
经验证,备份单个库没有问题。存在的不足是,恢复的时候,数据目录必须为空。也就是说,在恢复阶段,需要将现有的数据目录改名为临时目录;
在恢复之后,将原数据目录(现临时目录)下的其他库的内容拷贝到数据目录下即可。

##########################################
二:增量备份测试
增量备份测试主要通过测试以下几个场景,对数据备份和恢复进行验证。
1:全库备份,创建数据库,增量备份,恢复测试
全库备份
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf /backup/data
       
创建数据库
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'create database backup_test_tmp;'
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'create table backup_test_tmp.test (id int);'
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'insert into backup_test_tmp.test values(1),(2),(3),(4),(5);'
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'select * from backup_test_tmp.test;'
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    5 |
+------+
       
增量备份
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --incremental --incremental-basedir=/backup/data/2016-08-23_02-40-12 /backup/data/inc

关闭数据库服务:
kill -9 $(ps -ef|grep "mysql"|gawk '$0 !~/grep/ {print $2}' |tr -s '\n' ' ')

删除当前数据文件:
rm -rf /mysql/data/*
rm -rf /mysql/logs/*

恢复全备份日志文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --apply-log /backup/data/2016-08-23_02-40-12


恢复增量备份日志文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --apply-log /backup/data/2016-08-23_02-40-12 --incremental-dir=/backup/data/inc/2016-08-23_02-46-24
  
恢复增量备份数据文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --copy-back /backup/data/2016-08-23_02-40-12

数据验证:
chown -R mysql:mysql /mysql
mysqld_safe --defaults-file=/etc/my.cnf &
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'select * from backup_test.test;'
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    5 |
+------+

测试结果:
经验证,备份恢复正确。


****************************************************************
2:全库备份,修改数据表结构,增量备份,恢复测试
全库备份
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf /backup/data


修改数据表结构
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e 'alter table backup_test.test add email varchar(20) default "null";'
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'select * from backup_test.test;'
+------+-------+
| id   | email |
+------+-------+
|    1 | null  |
|    2 | null  |
|    3 | null  |
|    4 | null  |
|    5 | null  |
+------+-------+


增量备份
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --incremental --incremental-basedir=/backup/data/2016-08-24_03-05-41 /backup/data/inc


关闭数据库服务:
kill -9 $(ps -ef|grep "mysql"|gawk '$0 !~/grep/ {print $2}' |tr -s '\n' ' ')


删除当前数据文件:
rm -rf /mysql/data/*
rm -rf /mysql/logs/*


恢复全备份日志文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --apply-log /backup/data/2016-08-24_03-05-41


恢复增量备份日志文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --apply-log /backup/data/2016-08-24_03-05-41 --incremental-dir=/backup/data/inc/2016-08-24_03-07-21


恢复增量备份数据文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --copy-back /backup/data/2016-08-24_03-05-41


数据验证:
chown -R mysql:mysql /mysql
service mysql start
mysqld_safe --defaults-file=/etc/my.cnf &
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'select * from backup_test.test;'
+------+-------+
| id   | email |
+------+-------+
|    1 | null  |
|    2 | null  |
|    3 | null  |
|    4 | null  |
|    5 | null  |
+------+-------+
 
测试结果:
经验证,增量备份没有问题。存在的不足是,恢复的时候,首先数据目录必须为空,其次,恢复的时候需要单独拷贝增量备份的表结构。
也就是说,在恢复阶段,需要将数据目录清空;数据恢复后,需要单独拷贝增量备份文件夹下的表结构。


************************************************
3:全备份某库,修改库,增量备份,恢复测试
全备份某库
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --database=backup_test /backup/data

修改库
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'alter table backup_test.test add address varchar(20) default "null";'
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'select * from backup_test.test;'
+------+-------+---------+
| id   | email | address |
+------+-------+---------+
|    1 | null  | null    |
|    2 | null  | null    |
|    3 | null  | null    |
|    4 | null  | null    |
|    5 | null  | null    |
+------+-------+---------+

增量备份
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --database=backup_test --incremental --incremental-basedir=/backup/data/2016-08-24_06-39-42 /backup/data/inc

关闭数据库服务:
kill -9 $(ps -ef|grep "mysql"|gawk '$0 !~/grep/ {print $2}' |tr -s '\n' ' ')

删除当前数据文件:
rm -rf /mysql/data/backup_test/*

恢复全备份日志文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --database=backup_test --apply-log /backup/data/2016-08-24_06-39-42


恢复增量备份日志文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --database=backup_test --apply-log /backup/data/2016-08-24_06-39-42 --incremental-dir=/backup/data/inc/2016-08-24_06-41-48
       
恢复增量备份数据文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --database=backup_test --copy-back /backup/data/2016-08-24_06-39-42
cp /mysql/databak/* /mysql/data                                              (仅拷贝不在data中的文件)

数据验证:
chown -R mysql:mysql /mysql
mysqld_safe --defaults-file=/etc/my.cnf &
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'select * from backup_test.test;'
+------+-------+---------+
| id   | email | address |
+------+-------+---------+
|    1 | null  | null    |
|    2 | null  | null    |
|    3 | null  | null    |
|    4 | null  | null    |
|    5 | null  | null    |
+------+-------+---------+
 
测试结果:
经验证,增量备份没有问题。存在的不足是,恢复的时候,首先数据目录必须为空,其次,恢复的时候需要单独拷贝增量备份的表结构。也就是说,在恢复阶段,需要将现有的数据目录改名为临时目录;
在恢复之后,将原数据目录(现临时目录)下的其他库的内容拷贝到数据目录下即可。数据恢复后,还需要单独拷贝增量备份文件夹下的表结构。

********************************************************
4:全库备份,创建数据库,增量备份,修改表结构,增量备份,恢复测试
全库备份
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf /backup/data


创建数据库
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'drop database backup_test_tmp;'
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'create database backup_test_tmp;'
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'create table backup_test_tmp.test (id int);'
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'insert into backup_test_tmp.test values(1),(2),(3),(4),(5);'
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'select * from backup_test_tmp.test;'
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    5 |
+------+
       _
第一次增量备份
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --incremental --incremental-basedir=/backup/data/2016-08-24_08-53-11 /backup/data/inc

修改数据表结构
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'alter table backup_test_tmp.test add email varchar(20) default "null";'
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'select * from backup_test_tmp.test;'
+------+-------+
| id   | email |
+------+-------+
|    1 | null  |
|    2 | null  |
|    3 | null  |
|    4 | null  |
|    5 | null  |

+------+-------+


第二次增量备份
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --incremental --incremental-basedir=/backup/data/inc/2016-08-24_08-54-11 /backup/data/inc
这里以第一次增量备份的目录为基础

关闭数据库服务:
kill -9 $(ps -ef|grep "mysql"|gawk '$0 !~/grep/ {print $2}' |tr -s '\n' ' ')

删除当前数据文件:
rm -rf /mysql/data/*
rm -rf /mysql/logs/*

恢复全备份日志文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --apply-log /backup/data/2016-08-24_08-53-11

恢复增量备份1日志文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --apply-log /backup/data/2016-08-24_08-53-11 --incremental-dir=/backup/data/inc/2016-08-24_08-54-11

恢复增量备份2日志文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --apply-log /backup/data/2016-08-24_08-53-11 --incremental-dir=/backup/data/inc/2016-08-24_08-55-39

恢复增量备份数据文件:
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --copy-back --user=backup /backup/data/2016-08-24_08-53-11

数据验证:
chown -R mysql:mysql /mysql
mysqld_safe --defaults-file=/etc/my.cnf &
mysql -uroot -p123456 -S/usr/local/mysql/mysql.sock -e'select * from backup_test_tmp.test;'
+------+-------+
| id   | email |
+------+-------+
|    1 | null  |
|    2 | null  |
|    3 | null  |
|    4 | null  |
|    5 | null  |
+------+-------+
测试结果:
经验证,增量备份没有问题。存在的不足是,恢复的时候,首先数据目录必须为空,其次,恢复的时候需要单独拷贝最后一次增量备份的表结构。
也就是说,在恢复阶段,需要将数据目录清空;数据恢复后,需要单独拷贝最后一次增量备份文件夹下的表结构。

#####################################

Xreabackup实现原理
对于InnoDB,XtraBackup基于InnoDB的crash-recovery功能进行备份。
crash-recovery是这样的:InnoDB维护了一个redo log,又称为 transaction log,也叫事务日志,它包含了InnoDB数据的所有改动情况。
InnoDB启动的时候先去检查datafile和transaction log,然后应用所有已提交的事务并回滚所有未提交的事务。
XtraBackup在备份的时候并不锁定表,而是一页一页地复制InnoDB的数据,与此同时,XtraBackup还有另外一个线程监视着transactions log,
一旦log发生变化,就把变化过的log pages复制走(因为transactions log文件大小有限,写满之后,就会从头再开始写,新数据可能会覆盖到
旧的数据,所以一旦变化就要立刻复制走)。在全部数据文件复制完成之后,停止复制logfile。
XtraBackup采用了其内置的InnoDB库以read-write模式打开InnoDB的数据文件,然后每次读写1MB(1MB/16KB=64page)的数据,一页一页地遍历,
同时用InnoDB的buf_page_is_corrupted()函数检查此页的数据是否正常,如果正常则进行复制,如不正常则重新读取,最多重读10次,如果还
是失败,则备份失败退出。复制transactions log的原理也是一样的,只不过每次读写512KB(512KB/16KB=32page)的数据。
由于XtraBackup其内置的InnoDB库打开文件的时候是rw的,所以运行XtraBackup的用户,必须对InnoDB的数据文件具有读写权限。
由于XtraBackup要从文件系统中复制大量的数据,所以它尽可能地使用posix_fadvise(),来告诉OS不要缓存读取到的数据(因为这些数据不会
重用到了),从而提升性能。如果要缓存的话,大量的数据会对OS的虚拟内存造成很大的压力,其它进程(如mysqld)很有可能会被swap出去,
这样就出问题了。同时,XtraBackup在读取数据的时候还尽可能地预读。

由于不锁表,所以复制出来的数据是不一致的,数据的一致性是在恢复的时候使用crash-recovery进行实现的。


#############################################

Xreabackup配置mysql复制:

1:.环境描述
主从环境
master:192.168.1.23
slave:192.168.1.24

2:.Master创建复制用户
GRANT REPLICATION SLAVE ON *.* TO repl@'192.168.1.%' IDENTIFIED BY 'repl'; 


3.Master上备份数据库并传输
mkdir -p /backup/data
cd /backup/data
innobackupex --defaults-file=/etc/my.cnf--user=root --password=123456 --slave-info --safe-slave-backup--socket=/tmp/mysql.sock --no-timestamp /backup/data

查看xtrabackup_binlog_info信息:
more xtrabackup_binlog_info
bin.000003      1203   

scp -r * mysql4:/backup/data/

5.将备份恢复到slave
innobackupex --apply-log/backup/data/     
--apply-log                           应用日志

innobackupex --copy-back /backup/data/
--copy-back    把文件按照/etc/my.cnfcopy到数据目录

6.启动数据库
/etc/init.d/mysqld start

7.配置slave replication
CHANGE MASTER TO
MASTER_HOST='192.168.1.24',
MASTER_USER='repl',
MASTER_PASSWORD='repl',
MASTER_LOG_FILE=' bin.000003',
MASTER_LOG_POS=1203;
start slave;
show slave status\G

配置完成。


 类似资料: