Xtrabackup异机远程备份
随着公司业务的不断扩大,数据量也日益渐涨。往往人们总是觉得一般不会出什么大问题,从而容易忽略数据备份的重要性。以下是我所在环境的数据备份方案场景。大多数公司还是比较喜欢用云服务器节省资源,当然愿意花钱的可以用云厂商提供的备份工具。拥有独立IDC的可以使用专业备份设备本地+异地通过光纤备份,效率和安全都是极致的。我现在的环境就是比较尴尬的一种,首先数据库等业务环境都在云服务器上,但是云服务器没有较大的空间去存储备份,也不愿去采用厂商的备份工具。这就需要我们将备份拉取的本地进行存储。在此之前他们原有的备份方式是采用破解的MySQL客户端工具Navicat Premium在本地进行远程备份,这种方法可以备份,但是存在各种问题。首先你是用的非正版,出了问题你除了百度别无他法,再者这种工具拿来备份的人是极少的,你在百度上搜素也找不到多少相关的文章,所以是一个较大的坑。另一方面根据实际观察,这玩意在本地进行备份走的是MySQL的公网,且不说备份速度极慢,备份期间长时间占满MySQL服务器的出网带宽,这是我们不愿看到的现象。
数据备份我们要遵守以下几点:
1.备份时不能影响业务正常运行,则需要热备
2.备份效率要高(数据量不大却要备份四五个小时,这种方式肯定不能要)
3.备份的完整性(我们备份的数据不是仍在存储里就可以了,它要在出现意外故障的时候能用得上)
4.备份的最小化(存储也是要花钱的,我们当然需要,备份保留的时间最长,占用的空间越小越好)
1.1拓扑图
1.2 Xtrabackup介绍
PerconaXtraBackup[A1] 是一个免费的、在线的、开放源码的、针对MySQL和MySQL的Percona Server所有版本的完整数据库备份解决方案。PerconaXtraBackup在事务性系统上执行在线非阻塞、严格压缩、高度安全的完全备份,以便应用程序在计划的维护窗口中仍然完全可用。
1.3 备份方式
l 热备份:读写不受影响(mysqldump-->innodb)
l 温备份:仅可以执行读操作(mysqldump-->myisam)
l 冷备份:离线备份,读写都不可用
l 逻辑备份:将数据导出文本文件中(mysqldump)
l 物理备份:将数据文件拷贝(xtrabackup、mysqlhotcopy)
l 完整备份:备份所有数据
l 增量备份:仅备份上次完整备份或增量备份以来变化的数据
l 差异备份:仅备份上次完整备份以来变化的数据
xtrabackup是一种物理备份工具,通过协议连接到mysql服务端,然后读取并复制innodb底层的"数据块",完成所谓的"物理备份"。
1.4 xtrabackup 特点
1、备份过程快速、可靠;
2、备份过程不会打断正在执行的事务;
3、能够基于压缩等功能节约磁盘空间和流量;
4、自动实现备份检验;
5、还原速度快;
* 热备
* 增量
* 差量
Xtrabackup有两个主要的工具:
l xtrabackup
l innobackupex
1.xtrabackup 是用来备份 InnoDB 表的,不能备份非 InnoDB 表,和 mysqld server 没有交互;
2.innobackupex 脚本用来备份非 InnoDB 表,同时会调用 xtrabackup 命令来备份 InnoDB 表,还会和 mysqld server 发送命令进行交互,如加读锁(FTWRL)、获取位点(SHOW SLAVE STATUS)等
简单来说,innobackupex 在 xtrabackup 之上做了一层封装。
一般情况下,我们是希望能备份 MyISAM 表的,虽然我们可能自己不用 MyISAM 表,但是 mysql 库下的系统表是 MyISAM 的,因此备份基本都通过 innobackupex 命令进行。
[A1]Facebook是PerconaXtraBackup中增量备份的早期采用者
1.5 备份脚本
1.5.1 数据库端
#!/bin/sh # #descriptiom: mysql data_back #date: 2020-04-23 #备份主机 db_host='10.0.0.1' #生产:10.0.0.1 #预发布:10.0.0.2 #备份用户 db_user='root' #密码 db_pwd='123456789' #生产:123456789 #预发布:123456789 #时间 dates=`date "+%Y-%m-%d-%H:%M"` dates1=`date "+%Y-%m-%d"` #备份目录 db_full='/home/mysql/back/full' db_incremental='/home/mysql/back/incremental' db_local1='/home/mysql/back/full/chkpoint' db_local2='/home/mysql/back/incremental/chkpoint' #数据库 db_name='test' #生产:test #预发布:test #日志路径 db_log='/home/mysql/log' ############################ if [ ! -d $db_local1 ] then mkdir -p $db_local1 fi if [ ! -d $db_local2 ] then mkdir -p $db_local2 fi if [ ! -d $db_log ] then mkdir -p $db_log fi ############################ #日志 function log_info () { if [ -d $db_log/dbback ] then touch $db_log/dbback fi DATE_N=`date "+%Y-%m-%d %H:%M:%S"` USER_N=`whoami` echo "${DATE_N} ${USER_N} execute $0 [INFO] $@" >>$db_log/dbback } function log_error (){ DATE_N=`date "+%Y-%m-%d %H:%M:%S"` USER_N=`whoami` echo -e "\033[41;37m ${DATE_N} ${USER_N} execute $0 [ERROR] $@ \033[0m" >>$db_log/dbback } function fn_log () { if [ $? -eq 0 ] then log_info "$@ sucessed." echo -e "\033[32m $@ sucessed. \033[0m" else log_error "$@ failed." echo -e "\033[41;37m $@ failed. \033[0m" exit 1 fi } trap 'fn_log "do not send CTR + C when excute script !!!! "' 2 #全量备份 Full (){ innobackupex --defaults-file=/etc/my.cnf --host=$127.0.0.1 --user=$db_user --password=$db_pwd --databases=$db_name --stream=xbstream --compress --extra-lsndir=$db_local1 $db_full|gzip|ssh root@10.31.233.247 "cat >/worker/db_back/full/$dates1.gz" B_tat=`echo $?` if [ $B_tat -eq 0 ] then B_size=`ssh root@中转服务器IP "ls -lh /worker/db_back/full"|awk -F "[ ]" '{print $5,$9}'` fn_log "全量备份成功 $B_size" ssh root@中转服务器IP "ls -lh /worker/db_back/full"|awk -F "[ ]" 'NR==2{for (i=4;i<=NF;i++)printf("%s ", $i);print ""}'>>/home/mysql/log/mail.txt mail -s "MySQL data backup" yunwei@163.com </home/mysql/log/mail.txt >/home/mysql/log/mail.txt else fn_log "全量备份失败" echo "全量备份失败"|mail -s "MySQL data backup" yunwei@163.com fi } #增量备份 incremental (){ innobackupex --defaults-file=/etc/my.cnf --host=127.0.0.1 --user=$db_user --password=$db_pwd --databases=$db_name --stream=xbstream --compress --incremental --extra-lsndir=db_local1 --incremental-basedir=$db_local1 $db_incremental |gzip|ssh root@10.31.233.247 "cat >/worker/db_back/incremental/$dates1.gz" B_tat1=`echo $?` if [ $B_tat1 -eq 0 ] then B_size1=`ssh root@中转服务器IP "ls -lh /worker/db_back/incremental"|awk -F "[ ]" '{print $5,$9}'` fn_log "增量备份成功 $B_size1" ssh root@中转服务器IP "ls -lh /worker/db_back/incremental"|awk -F "[ ]" 'NR==2{for (i=4;i<=NF;i++)printf("%s ", $i);print ""}'>>/home/mysql/log/mail.txt mail -s "MySQL data backup" yunwei@163.com </home/mysql/log/mail.txt >/home/mysql/log/mail.txt else fn_log "增量备份失败" echo "增量备份失败"|mail -s "MySQL data backup" yunwei@163.com fi } case $1 in Full) Full ;; incremental) incremental ;; *) echo "Please use it this way. Usage:$0 {Full|incremental}" ;; esac
1.5.2 中转站脚本
[root@ ~]# cd /data/scripts/ [root@ scripts]# ll total 4 -rwxr-xr-x 1 root root 406 May 25 14:31 backup.sh [root@ scripts]# cat backup.sh #!/bin/sh # #descriptiom: mysql databack #date: 2020-05-22 #备份清理 #时间 dates=`date "+%Y-%m-%d-%H:%M"` dates1=`date "+%Y-%m-%d"` #备份保留时间(天) Rtime='1' #备份目录 db_full='/worker/db_back/full' db_incremental='/worker/db_back/incremental' find $db_full -mtime +$Rtime -name "*.gz" -exec rm -rf {} \; find $db_incremental -mtime +$Rtime -name "*.gz" -exec rm -rf {} \;
1.5.3 本地存储端
#!/bin/sh # #descriptiom: mysql databack #date: 2020-05-22 #备份清理 #时间 dates=`date "+%Y-%m-%d-%H:%M"` dates1=`date -d '-1 day' '+%Y-%m-%d'` #备份保留时间(天) Rtime='90' #备份目录 db_full='/home/mysql/back/full' db_incremental='/home/mysql/back/incremental' if [ ! -d $db_full ] then mkdir -p $db_full fi if [ ! -d $db_incremental ] then mkdir -p $db_incremental fi week=`date +%w` if [ $week -eq 2 ] then sshpass -p 中转服务器密码 scp -rp root@中转服务器外网IP:/worker/db_back/full/$dates1.gz $db_full B_stat=`echo $?` if [ $B_stat -eq 0 ] then B_size=`ls -lh $db_full/$dates1.gz|awk -F "[ ]" 'NR==1{for (i=4;i<=NF;i++)printf("%s ", $i);print ""}'` echo "全量备份拉取完成 $B_size"|mail -s "MySQL data backup" yunwei@163.com else echo "全量备份拉取失败"|mail -s "MySQL data backup" yunwei@163.com fi else sshpass -p 中转服务器密码 scp -rp root@中转服务器外网IP:/worker/db_back/incremental/$dates1.gz $db_incremental B_stat1=`echo $?` if [ $B_stat1 -eq 0 ] then B_size1=`ls -lh $db_incremental/$dates1.gz|awk -F "[ ]" 'NR==1{for (i=4;i<=NF;i++)printf("%s ", $i);print ""}'` echo "增量备份拉取完成 $B_size1"|mail -s "MySQL data backup" yunwei@163.com else echo "增量备份拉取失败"|mail -s "MySQL data backup" yunwei@163.com fi fi find $db_full -mtime +$Rtime -name "*.gz" -exec rm -rf {} \; find $db_incremental -mtime +$Rtime -name "*.gz" -exec rm -rf {} \;