架构
异机还原IP:172.17.100.103(5.6.39)
还原IP:172.17.100.104(5.6.39)
线上备份:阿里云RDS(5.6.16)
备份IP:172.17.100.100(5.7.22)
实验一:Xtrabackup流备
惯例性的先处理报错
报错原因:InnoDB: Error number 24 means 'Too many open files'
检查系统层面的参数ulimit
可以看到open files对应的是-n
ulimit -n 65535将该值修改为65535
或者修改/etc/security/limits.conf
在最底下添加2行,然后logout重新登陆会话
在/etc/my.cnf里面添加
open_files_limit=20480
重启mysql
发现该参数已经得到修改
重新执行innobackupex,正常执行。
#执行流备到异机
innobackupex --defaults-file=/data/mysql/mysql3306/my3306.cnf -uroot -pbeacon --stream=tar /tmp | ssh [email protected] \ "cat - > /data/Xtrabackup/bak.tar"
第一个粗体是本机的路径;第二个粗体引号前面一定要有空格,否则引号会被转义;第三个粗体是异机的路径
实际执行中,本机路径下不会生成任何文件,最终的文件会被生成到异机的指定路径下
最终这个bak.tar会生成到172.17.100.103的/data/Xtrabackup路径下
注意的是,如果用tar压缩成了gz文件,在103上执行解压时需要采用-i参数
tar -xif bak.tar.gz
在103上恢复之前,需要prepare;因为流式备份不会prepare
实验二:Xtrabackup增量备份
插曲
之前把线上的5.6版本的mysql恢复到本机5.6和5.7的库上均没有问题
今天试了下,把5.7的库恢复到5.6,提示为失败
MySQL支持向后兼容,但是向前是不行滴
#首先做一个全备
innobackupex --defaults-file=/data/mysql/mysql3306/my3306.cnf -uroot -pbeacon /data/Xtrabackup/
#数据库进行一次事务操作
#基于前面的全备进行增备
全备路径:/data/Xtrabackup/
增备路径:/data/Incremental/
innobackupex --defaults-file=/data/mysql/mysql3306/my3306.cnf -uroot -pbeacon --incremental --incremental-basedir=/data/Xtrabackup/2018-07-05_17-25-03/ /data/Incremental/
第一个粗体部分是全备的路径;第二个粗体部分是增备路径
查看lsn的变化
#基于增备进行增备
前面一次增备的lsn为57454873398
innobackupex --defaults-file=/data/mysql/mysql3306/my3306.cnf -uroot -pbeacon --incremental --incremental-lsn=57454873398 /data/Incremental/
基于前面的(2次)增备进行还原
①#将全量备份直接解压到数据路径下/data/mysql/mysql3306/data/
#基于全量的还原(和普通全量还原相比,就是多了一个--redo-only参数)
innobackupex --defaults-file=/data/mysql/mysql3306/my3306.cnf --apply-log --redo-only /data/mysql/mysql3306/data/
②#将增量备份(除开最后一次)解压到其他路径下/data/Incremental/2018-07-05_17-26-22/
#基于前面的全量,进行增量(除开最后一次增量)的还原,有--redo-only参数,还有--incremental-dir参数;最后跟着全量恢复的路径
innobackupex --defaults-file=/data/mysql/mysql3306/my3306.cnf --apply-log --redo-only --incremental-dir=/data/Incremental/2018-07-05_17-26-22/ /data/mysql/mysql3306/data/
③#将最后一次增量备份解压到对应路径下/data/Incremental/2018-07-05_17-35-04/
#基于前面的增量完成最后一次增量的恢复,没有--redo-only参数,incremental-dir写成最后一次增备的路径
innobackupex --defaults-file=/data/mysql/mysql3306/my3306.cnf --apply-log --incremental-dir=/data/Incremental/2018-07-05_17-35-04/ /data/mysql/mysql3306/data/
修改数据路径的权限为mysql,打开数据库,确认恢复成功
实验三:使用Xtrabackup备份脚本完成线上数据到线下数据的基于时间点的恢复
这并不是一个完整的线上全自动备份到线下的脚本,单纯只是一次半自动的恢复记录
本次实验前提:公司研发搭建了一个中间库,需要把线上RDS数据导入,这个中间库并不能直接连入阿里RDS内网,所以需要手动去下载数据备份(以及相应的日志备份);在执行这个脚本之前,需要确保该脚本同路径下有阿里的rds_backup_extract.sh脚本存在,阿里RDS自身有一些设定,通过常规情况下执行tar -xif强行解压会无法清除数据库密码,导致恢复后无法进入
阿里RDS下载名以hins开头,这个脚本的原理是:(hins文件通过ftp传输到中间库服务器之后)首先判定本地数据库是否开启(并执行关闭),将数据备份恢复到中间库,显示出当前恢复到的binlog号以及位置点(供执行者去下载),之后删除hins备份
#! /bin/bash
#判断MySQL是否启动(杀死进程)
pid=`ps -ef|grep '/usr/local/mysql/bin/mysqld --defaults-file=/data/mysql/mysql3306/my3306.cnf'|grep -v grep|awk '{print $2}'`
if [ -z "$pid" ]; then
echo "mysql is down" > /tmp/dump.log
else
kill -9 $pid
fi
rm -rf /data/mysql/mysql3306/data/*
rm -rf /data/mysql/mysql3306/logs/*
cd /home/run
#解压hins包,清除密码
sh rds_backup_extract.sh -f hins* -C /data/mysql/mysql3306/data
if [ $? == 0 ];then
echo -e "解压缩完成\n"
else
echo -e "解压失败\n"
exit 1
fi
#执行恢复
innobackupex --defaults-file=/data/mysql/mysql3306/my3306.cnf --apply-log /data/mysql/mysql3306/data
chown -R mysql.mysql /data/mysql
/usr/local/mysql/bin/mysqld --defaults-file=/data/mysql/mysql3306/my3306.cnf &
#判定mysql启动情况
while((1<100))
do
tail -10 /data/mysql/mysql3306/data/error.log |grep 'ready for connections' &>> /tmp/dump.log
if [ $? == 0 ];then
echo -e "mysql启动完成\n"
break
else
echo -e "mysql启动中...\n"
sleep 10
fi
done
#启动MySQL并执行升级等一系列操作
mysql_upgrade -uroot &>> /tmp/dump.log &&
mysql -uroot << EOF
delete from mysql.db where user<>'root' and char_length(user)>0;
delete from mysql.tables_priv where user<>'root' and char_length(user)>0;
flush privileges;
EOF
#判定binlog文件号以及后续binlog恢复的初始恢复点
A=`cat /data/mysql/mysql3306/data/xtrabackup_binlog_info|sed -n 1p|awk '{print $1}'`
B=`cat /data/mysql/mysql3306/data/xtrabackup_binlog_info|sed -n 1p|awk '{print $2}'`
echo -e "初始binlog为:$A"
echo -e "初始恢复点为:$B"
sleep 10
#清理hins文件
rm -rf hins*
重启之后恢复正常
如果重启之后没有恢复,那么执行mysql_upgrade,之后再进行重启
后续操作,根据前面提示的binlog号去RDS里下载该binlog号以及之后的所有binlog文件到本地
重启完成后,执行下一步根据binlog的pos点的恢复
根据该脚本的执行结果,此次恢复的初始binlog和对应pos点已经找出
分别为mysql-bin.000873和21286780
将对应binlog解压成可阅读的log,寻找pos点
mysqlbinlog -v --base64-output=DECODE-ROWS mysql-bin.000880 > 880.log
读取880.log,找到临界点的那个(误删除)操作对应的pos点为425318655
(由于生产环境是主从环境,所以在binlog里面可以找到2个server id,需要判断需要恢复的库的server id到底是哪一个,然后找到对的那个pos点)
根据pos点进行的全库恢复:
mysqlbinlog --start-position=21286780 --stop-position=425318655 mysql-bin.000873 mysql-bin.000874 mysql-bin.000875 mysql-bin.000876 mysql-bin.000877 mysql-bin.000878 mysql-bin.000879 mysql-bin.000880|mysql -uroot
根据pos点对某个库的恢复:
mysqlbinlog --start-position=21286780 --stop-position=425318655 --database=csds_db mysql-bin.000873 mysql-bin.000874 mysql-bin.000875 mysql-bin.000876 mysql-bin.000877 mysql-bin.000878 mysql-bin.000879 mysql-bin.000880|mysql -uroot
由于全库恢复量巨大,上面第一条的全库恢复语句在虚拟机上执行后没过多久就卡死掉了,强行终止还会损坏log文件,导致数据库无法正常打开;采用第二条对单库的恢复语句在短短的几分钟后就完成了恢复工作
参考文档:艺龄妹子的流备
参考文档:艺龄妹子的流备脚本