XtraBackup应用说明(支持TokuDB)
背景:
关于物理备份工具xtrabackup的一些说明可以先看之前写过的文章说明:XtraBackup 安装使用和xtrabackup 使用说明(续),本篇文章将介绍xtrabackup在使用中的注意事项和如何全量、增量备份和恢复,包含TokuDB的备份(感谢吴总的推荐)。由于物理备份消耗的空间比较大,所以在工作中一直使用mydumper进行备份,通过逻辑备份虽然空间使用上又很大改善,但是由于还原的时候需要消耗很长时间才能使用,也非常令人头疼。现在准备在生产环境中使用XtraBackup,记录使用中的一些注意事项。
安装:
环境:
XtraBackup版本为:2.4系统版本:14.04、16.04MySQL版本:5.7.16
说明:因为生产环境中有使用到TokuDB引擎,而Percona版本的XtraBackup不支持对TokuDB的备份,所以不能使用官方的版本。不过有人基于官方版本进行了修改,支持Tokudb的备份,下载地址:https://github.com/XeLabs/tokudb-xtrabackup,作者是BohuTANG。编译安装过程:
① 下载:
git clone https://github.com/XeLabs/tokudb-xtrabackup.git
② 安装依赖包:
apt-get install build-essential flex bison automake autoconf \ libtool cmake libaio-dev mysql-client libncurses-dev zlib1g-dev \ libgcrypt11-dev libev-dev libcurl4-gnutls-dev vim-common
③ 编译安装
#程序目录 mkidr /usr/local/xtrabackup_dir/#编译 cd tokudb-xtrabackup cmake . -DBUILD_CONFIG=xtrabackup_release -DWITH_BOOST=extra/boost/boost_1_59_0.tar.gz -DWITH_MAN_PAGES=OFF -DCMAKE_INSTALL_PREFIX=/usr/local/xtrabackup_dir/make VERBOSE=1make -j8 #安装make install
安装成功之后,文件里的信息如下:
/usr/local/xtrabackup_dir/bin# ls -lh总用量 200M lrwxrwxrwx 1 root root 10 8月 21 11:51 innobackupex -> xtrabackup-rwxr-xr-x 1 root root 5.2M 8月 21 11:22 xbcloud-rwxr-xr-x 1 root root 3.0K 8月 21 11:17 xbcloud_osenv-rwxr-xr-x 1 root root 5.0M 8月 21 11:22 xbcrypt-rwxr-xr-x 1 root root 5.1M 8月 21 11:22 xbstream-rwxr-xr-x 1 root root 185M 8月 21 11:32 xtrabackup
因为包含了一些符号信息和调试信息,xtrabackup文件很大,通过strip进行剥离:
strip xtrabackup
备份使用说明:
限制:
对于上面编译好的XtraBackup,对于备份TokuDB引擎有个限制,即不能指定tokudb_data_dir变量,必须使用默认参数。并且MySQL5.7也已经把TokuDB文件放入到对应的数据库文件夹中。
备份策略:
.每周日进行全量备份,周一至周六进行基于全量备份的增量备份。这样即使还原周四的备份,也只要prepare全量和周四增量的备份即可,不需要把周四之前的增量全部apply。 .备份文件不存本地,直接远程保存到备份服务器。 .备份一个从库,还原完成直接当从库来使用。
环境:
MySQL A服务器(备份) XtraBackup B备份服务器 MySQL C服务器(还原)
MySQL配置文件中配置目录的相关参数:日志文件(error log、binlog)最好别放数据目录里。
innodb_undo_directory = /var/lib/mysql/undolog/tokudb_log_dir = /var/lib/mysql/tokudb_log
注意:三台服务器上最好都装上XtraBackup,并且A和C的MySQL的配置文件配置的目录需要一致,如:undolog目录、tokudb目录等。关于备份相关的命令可以看之前写的文章,本文的备份命令如下:
1)全量备份,每周日进行
/usr/local/xtrabackup_dir/bin/xtrabackup --defaults-extra-file=/etc/mysql/xtrabackup.cnf --datadir=/var/lib/mysql --host=A --no-timestamp --slave-info --safe-slave-backup --ftwrl-wait-query-type=all --history --backup --parallel=5 --compress --compress-threads=3 --stream=xbstream --encrypt=AES256 --encrypt-key-file=/opt/bin/keyfile --encrypt-threads=3 | ssh B "/usr/local/xtrabackup_dir/bin/xbstream -x -C /data/"
解释:通过实际情况指定需要的参数,压缩加密打包到远程服务器,并在远程服务器解包到指定的目录。
--defaults-extra-file :该选项指定了在标准defaults-file之前从哪个额外的文件读取MySQL配置,必须在命令行的第一个选项的位置。一般用于存备份用户的用户名和密码的配置文件。--datadir :backup的源目录,mysql实例的数据目录。从my.cnf中读取,或者命令行指定。--host:该选项表示备份数据库的地址。--no-timestamp:该选项可以表示不要创建一个时间戳目录来存储备份,指定到自己想要的备份文件夹。--slave-info:该选项表示对slave进行备份的时候使用,打印出master的名字和binlog pos,同样将这些信息以change 。master的命令写入xtrabackup_slave_info文件。--safe-slave-backup:该选项表示为保证一致性复制状态,这个选项停止SQL线程并且等到show status中的slave_open_temp_tables为0的时候开始备份,如果没有打开临时表,bakcup会立刻开始,否则SQL线程将关闭直到没有打开的临时表。如果slave_open_temp_tables在--safe-slave-backup-timeount(默认300秒)秒之后不为0,从库sql线程会在备份完成的时候重启。--ftwrl-wait-query-type:该选项表示获得全局锁之前允许那种查询完成,默认是ALL,可选update。--history:该选项表示percona server 的备份历史记录在percona_schema.xtrabackup_history表。--backup:创建备份并且放入--target-dir目录中。--parallel:指定备份时拷贝多个数据文件并发的进程数,默认值为1。--compress:该选项表示压缩innodb数据文件的备份。--compress-threads:该选项表示并行压缩worker线程的数量。--stream:该选项表示流式备份的格式,backup完成之后以指定格式到STDOUT,目前只支持tar和xbstream。--encrypt:该选项表示通过ENCRYPTION_ALGORITHM的算法加密innodb数据文件的备份,目前支持的算法有ASE128,AES192,AES256。--encrypt-threads:该选项表示并行加密的worker线程数量。--encryption-key-file:该选项表示文件必须是一个简单二进制或者文本文件,加密key可通过以下命令行命令生成:openssl rand -base64 24。
在备份中,备份账号和密码存放在/etc/mysql/xtrabackup.cnf中,格式为:
[client] user=xtrabackup password=xtrabackup
生成加密key:
openssl rand -base64 24echo -n "5V05Dm+aFiRxZ6+sjfplK0K2YlbOplZn" > keyfile
该备份账号的权限:
>show grants for xtrabackup@localhost;+-------------------------------------------------------------------------------------------------------------------------+| Grants for xtrabackup@localhost |+-------------------------------------------------------------------------------------------------------------------------+| GRANT CREATE, RELOAD, PROCESS, SUPER, LOCK TABLES, REPLICATION CLIENT, CREATE TABLESPACE ON *.* TO 'xtrabackup'@'localhost' || GRANT SELECT, INSERT, CREATE ON `PERCONA_SCHEMA`.* TO 'xtrabackup'@'localhost' |+-------------------------------------------------------------------------------------------------------------------------+
2)增量备份:每周一至周六执行
/usr/local/xtrabackup_dir/bin/xtrabackup --defaults-extra-file=/etc/mysql/xtrabackup.cnf --datadir=/var/lib/mysql --host=A --no-timestamp --slave-info --safe-slave-backup --ftwrl-wait-query-type=all --history --backup --parallel=5 --compress --compress-threads=3 --stream=xbstream --encrypt=AES256 --encrypt-key-file=/opt/bin/keyfile --encrypt-threads=3 --incremental-lsn=NUM | ssh B "/usr/local/xtrabackup_dir/bin/xbstream -x -C /data/1/
解释:
--incremental-lsn:该选项表示指定增量备份的LSN,与--incremental选项一起使用。
因为增量备份是根据全量备份(target_dir)来进行的,由于全量已经传输到备份服务器,本地不存备份,所以需要通过记录当时全量备份时候的LSN,再基于此LSN进行增量备份。
备份信息说明
1:因为从库开了多线程复制(slave_parallel_workers),但没开启GTID,而XtraBackup要求2者必须都开启,否则报错:
The --slave-info option requires GTID enabled for a multi-threaded slave.
所以在备份脚本里进行了设置:备份开始前先设置成单线程复制,结束之后设置成多线程;也可以直接开启GTID。
2:由于开启了--safe-slave-backup参数,在一定时间里(--safe-slave-backup-timeout),默认300秒,若slave_open_temp_tables参数大于0则会暂停Slave的SQL线程,等待到没有打开的临时表的时候开始备份,备份结束后SQL线程会自动启动。要是备份时间比较长,少不了报警短信的骚扰。因为我在还原该备份完成之后,会对其进行主从一致性检验,就关闭了该参数进行备份。最终备份的命令如下:
1)全量备份
/usr/local/xtrabackup_dir/bin/xtrabackup --defaults-extra-file=/etc/mysql/xtrabackup.cnf --datadir=/var/lib/mysql --host=A --no-timestamp --slave-info --ftwrl-wait-query-type=all --backup --parallel=5 --compress --compress-threads=3 --stream=xbstream --encrypt=AES256 --encrypt-key-file=/opt/bin/keyfile --encrypt-threads=3 | ssh B "/usr/local/xtrabackup_dir/bin/xbstream -x -C /data/"
2)增量备份
/usr/local/xtrabackup_dir/bin/xtrabackup --defaults-extra-file=/etc/mysql/xtrabackup.cnf --datadir=/var/lib/mysql --host=A --no-timestamp --slave-info --ftwrl-wait-query-type=all --backup --parallel=5 --compress --compress-threads=3 --stream=xbstream --encrypt=AES256 --encrypt-key-file=/opt/bin/keyfile --encrypt-threads=3 --incremental-lsn=NUM | ssh B "/usr/local/xtrabackup_dir/bin/xbstream -x -C /data/1/
注意:编译的xtrabackup只支持TokuDB的全量备份,不支持增量备份。
为了方便,把备份命令放到python里面去执行,定制成一个备份脚本:(备份服务器B上先创建好目录。MySQL A服务器上再执行脚本)
MySQL A服务器上的脚本:
#!/usr/bin/env python#-*- encoding:utf-8 -*-import osimport sysimport timeimport datetimeimport smtplibimport subprocessimport reimport MySQLdbfrom email.mime.text import MIMETextfrom email.mime.multipart import MIMEMultipartfrom email.Utils import COMMASPACE, formatdate reload(sys) sys.setdefaultencoding('utf8') RETRIES = 1def retry_times(func): def wrapped(*args, **kwargs): global RETRIES try: return func(*args, **kwargs) except Exception, err: #重试次数 if RETRIES <= 10: print "\n邮件发送重试第【%s】次\n" %RETRIES RETRIES += 1 time.sleep(1) if RETRIES == 10: print "\n重试10次,邮件发送失败,exit...\n" sys.exit() return wrapped(*args, **kwargs) return wrapped @retry_timesdef send_mail(to, subject, text, from_mail, server="localhost"): message = MIMEMultipart() message['From'] = from_mail message['To'] = COMMASPACE.join(to) message['Date'] = formatdate(localtime=True) message['Subject'] = subject message.attach(MIMEText(text,_charset='utf-8')) smtp = smtplib.SMTP(server,timeout=3) smtp.sendmail(from_mail, to, message.as_string()) smtp.close()def getDate(): today = datetime.datetime.now().strftime('%Y-%m-%d') weekday = datetime.datetime.now().weekday() return today,weekdaydef getMonDay(num): monday = (datetime.date.today() - datetime.timedelta(days=num)).strftime("%Y-%m-%d") return mondaydef getTime(): now = datetime.datetime.now().strftime('%H:%M:%S') return nowdef getPath(): Path = os.path.realpath(os.path.dirname(__file__)) return Pathdef setSingleThread(conn): queries = '''\ STOP SLAVE;\ START SLAVE UNTIL SQL_AFTER_MTS_GAPS;\ SET @@GLOBAL.slave_parallel_workers = 0;\ START SLAVE SQL_THREAD\''' for query in queries.split(';'): cursor = conn.cursor()# print query time.sleep(0.5) cursor.execute(query)def setMultiThread(conn): queries = '''\ STOP SLAVE;\ START SLAVE UNTIL SQL_AFTER_MTS_GAPS;\ SET @@GLOBAL.slave_parallel_workers = 4;\ START SLAVE SQL_THREAD\''' for query in queries.split(';'): cursor = conn.cursor()# print query time.sleep(0.5) cursor.execute(query)def run_cmd(cmd): p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) ret_str = p.stdout.read() retval = p.wait() return ret_strif __name__ == "__main__": CWD = '/etc/mysql' db_conf = os.path.join(CWD, 'xtrabackup.cnf') conn = MySQLdb.connect(read_default_file=db_conf,host='localhost',port=3306,charset='utf8') instance_name = 'Job' local_host = 'localhost' remote_host = 'C' today,weekday = getDate() weekday = weekday + 1 print "\n\n\n\n\n备份执行日期是:%s, 星期%s\n" %(today,weekday)# today = '2017-08-20'# weekday = 7 if weekday == 7: setSingleThread(conn) print("\033[0;32m set single thread replication sucess... \033[0m") remote_backupfile = '/data/dbbackup_dir/job/%s/full_backup' %today print remote_backupfile print("\033[0;32m execute full backup... \033[0m")#--safe-slave-backup --safe-slave-backup-timeout=600 xtrabackup_fullbackup = '''/usr/local/xtrabackup_dir/bin/xtrabackup --defaults-extra-file=/etc/mysql/xtrabackup.cnf --datadir=/var/lib/mysql --host=%s --no-timestamp --slave-info --ftwrl-wait-query-type=all --backup --parallel=5 --compress --compress-threads=3 --stream=xbstream --encrypt=AES256 --encrypt-key-file=/opt/bin/keyfile --encrypt-threads=3 | ssh %s "/usr/local/xtrabackup_dir/bin/xbstream -x -C %s" ''' %(local_host,remote_host,remote_backupfile) print "\n执行全量备份的命令:\n%s\n" %xtrabackup_fullbackup res = run_cmd(xtrabackup_fullbackup) print res setMultiThread(conn) print("\033[0;32m set multi thread replication sucess... \033[0m") if res.find('completed OK!') > 0: _point = re.compile(ur'.*(xtrabackup: The latest check point \(for incremental\): )\'([0-9]+\.?[0-9]*)\'*') incremental_point = dict(_point.findall(res)).get('xtrabackup: The latest check point (for incremental): ') f = open(os.path.join(getPath(),'incremental_point.txt'),'w') f.write(incremental_point) f.close() if incremental_point: subject = '%s【%s】全量物理备份成功' %(today,instance_name) mail_list = ['[email protected]'] send_mail(mail_list, subject.encode("utf8"), 'Sucess!', "[email protected]", server="smtp.host.dxy") else : subject = '%s【%s】全量物理备份获取lsn失败' %(today,instance_name) mail_list = ['[email protected]'] send_mail(mail_list, subject.encode("utf8"), res, "[email protected]", server="smtp.host.dxy") else : subject = '%s【%s】全量物理备份失败' %(today,instance_name) mail_list = ['[email protected]'] send_mail(mail_list, subject.encode("utf8"), res, "[email protected]", server="smtp.host.dxy") else : setSingleThread(conn) print("\033[0;32m set single thread replication sucess... \033[0m") print("\033[0;32m execute incremental backup... \033[0m") monday = getMonDay(weekday) remote_backupfile = '/data/dbbackup_dir/job/%s/%s' %(monday,weekday)# print remote_backupfile try: f = open(os.path.join(getPath(),'incremental_point.txt'),'r') incremental_point = f.read() f.close() except Exception,e: incremental_point = None print e if incremental_point:#--safe-slave-backup --safe-slave-backup-timeout=600 xtrabackup_incrbackup = '''/usr/local/xtrabackup_dir/bin/xtrabackup --defaults-extra-file=/etc/mysql/xtrabackup.cnf --datadir=/var/lib/mysql --host=%s --no-timestamp --slave-info --ftwrl-wait-query-type=all --backup --parallel=5 --compress --compress-threads=3 --stream=xbstream --encrypt=AES256 --encrypt-key-file=/opt/bin/keyfile --encrypt-threads=3 --incremental-lsn=%s | ssh %s "/usr/local/xtrabackup_dir/bin/xbstream -x -C %s"''' %(local_host,incremental_point,remote_host,remote_backupfile) print "\n执行增量备份的命令:\n%s\n" %xtrabackup_incrbackup res = run_cmd(xtrabackup_incrbackup) print res setMultiThread(conn) print("\033[0;32m set multi thread replication sucess... \033[0m") if res.find('completed OK!') > 0: subject = '%s【%s】增量物理备份成功' %(today,instance_name) mail_list = ['[email protected]'] send_mail(mail_list, subject.encode("utf8"), 'Sucess!', "[email protected]", server="smtp.host.dxy") else : subject = '%s【%s】增量物理备份失败' %(today,instance_name) mail_list = ['[email protected]'] send_mail(mail_list, subject.encode("utf8"), res, "[email protected]", server="smtp.host.dxy") else : setMultiThread(conn) print("\033[0;32m set multi thread replication sucess... \033[0m") subject = '%s【%s】增量物理备份获取lsn失败' %(today,instance_name) mail_list = ['[email protected]'] send_mail(mail_list, subject.encode("utf8"), str(e) , "[email protected]", server="smtp.host.dxy")
备份服务器B上的脚本:
#!/usr/bin/env python#-*- encoding:utf-8 -*-import osimport sysimport timeimport datetimeimport commandsdef getDate(): today = datetime.datetime.now().strftime('%Y-%m-%d') weekday = datetime.datetime.now().weekday() return today,weekdaydef mkdir(path): isExists=os.path.exists(path) if not isExists: os.makedirs(path) print "创建成功!" else: print "文件夹存在!"if __name__ == "__main__": today,weekday = getDate() weekday = weekday + 1# print today,weekday if weekday == 7:# today = '2017-08-20' backup_path = '/data/dbbackup_dir/' instsance_names = ['test','test1','test2'] dir_names = ['full_backup','1','2','3','4','5','6'] for instsance_name in instsance_names: for dir_name in dir_names: dir_path = os.path.join(backup_path,instsance_name,today,dir_name) mkdir(dir_path) else : print "只在周日执行..."
模拟全量备份,备份流程原理的信息如下:
1):fork 一个子线程进行redo log 的复制2):主线程进行ibd文件复制,直到ibd文件复制完3):SET GLOBAL tokudb_checkpoint_lock=ON,它的作用是允许拿到checkpoint锁,此时TokuDB的checkpoint会一直block到该锁释放(执行前要把tokudb_checkpoint_on_flush_logs关掉),目的是防止拷贝TokuDB数据文件的过程中做sharp checkpoint(注意:由于不做checkpoint,TokuDB的日志文件会逐渐增多),从而导致数据文件内部不一致(已拷贝的文件被修改)4):LOCK TABLES FOR BACKUP1.禁止非innodb表更新2.禁止所有表的ddl 优化点:1.不会关闭表2.不会堵塞innodb表的读取和更新,对于业务表全部是innodb的情况,则备份过程中DML完全不受损。5):开始并完成备份非InnoDB表和文件6):LOCK BINLOG FOR BACKUP,获取一致性位点1.禁止对位点更新的操作2.允许DDl和更新,直到写binlog为止。7):FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS,写binlog,不轮询。8):开始和完成备份TokuDB的undo和redo9):记录LSN最后的点,停止redo log的线程的备份10):解锁binlog和tables11):开始和完成备份TokuDB文件12):SET GLOBAL tokudb_checkpoint_lock=OFF,解锁TokuDB的checkpoint锁。
增量备份则读取全量备份时候记录的点位进行备份(脚本里把点位写入到了文件中)。备份服务器的目录如下:
# du -sch 2017-08-20/* 4.0K 2017-08-20/1 4.0K 2017-08-20/2 4.0K 2017-08-20/3 4.0K 2017-08-20/4 4.0K 2017-08-20/5 4.0K 2017-08-20/6 33G 2017-08-20/full_backup33G total
到此,备份大致的流程已经介绍完毕,那么接着继续介绍如何还原。
还原使用说明:
1:全量备份的还原
因为通过上面的备份脚本已经把备份文件传输到了备份服务器B中,后面的相关操作只要在备份服务器B和MySQL服务器C中进行。
1)从备份服务器B中,把备份传到MySQL服务器C中。如备份目录为full_backup
scp -r full_backup/ C:/data/dbbackup_dir/
2)在MySQL服务器C中进行解密、解压和prepare。解密的key需要和上面加密时候生成的key保持一致!解压需要安装qpress。
#解密:for i in `find . -iname "*\.xbcrypt"`; do /usr/local/xtrabackup_dir/bin/xbcrypt -d --encrypt-key-file=/data/keyfile --encrypt-algo=AES256 < $i > $(dirname $i)/$(basename $i .xbcrypt) && rm $i; done#解压for f in `find ./ -iname "*\.qp"`; do qpress -dT2 $f $(dirname $f) && rm -f $f; done #prepare,需要执行2次,第1次回滚未提交和执行已提交的事务,第2次生成redo log,加快mysql启动时间。/usr/local/xtrabackup_dir/bin/xtrabackup --prepare --apply-log-only --use-memory=1G --target-dir=/data/dbbackup_dir/full_backup
备份文件说明:
root@db-test-xt:/data/dbbackup_dir/full_backup# ls -lh xtrabackup_* -rw-r--r-- 1 root root 27 Aug 22 10:28 xtrabackup_binlog_info-rw-r--r-- 1 root root 27 Aug 22 10:28 xtrabackup_binlog_pos_innodb-rw-r--r-- 1 root root 121 Aug 22 10:28 xtrabackup_checkpoints-rw-r--r-- 1 root root 687 Aug 22 10:27 xtrabackup_info-rw-r--r-- 1 root root 8.0M Aug 22 10:28 xtrabackup_logfile-rw-r--r-- 1 root root 83 Aug 22 10:24 xtrabackup_slave_info
xtrabackup_binlog_info:记录备份时的binlog点位,若有MyISAM存储引擎,以该点位准。 xtrabackup_binlog_pos_innodb:记录备份时的binlog点位,用于InnoDB、XtraDB的点位记录。 xtrabackup_checkpoints:记录备份模式(backup_type)以及放备份的起始位置beginlsn和结束位置endlsn等。 xtrabackup_slave_info:备份从库时记录的CHANGE信息。 xtrabackup_info:备份的具体信息,如备份命令、版本、开始结束时间、是否压缩、加密等信息。
经过上面的解密、解压、prepare之后,数据库的文件已经生成,现在需要做的就是把这些文件放到MySQL数据目录中。
3)还原,复制文件
注意:备份和还原的MySQL配置文件所配置的目录需要保持一致,如:undolog是否独立,tokudb必须不能指定目录,保证备份和还原MySQL目录的一致性。如果起来当一个从来服务则需要修改server_id。
1:复制文件到数据目录/data/dbbackup_dir# mv full_backup/* /var/lib/mysql/2:根据配置文件设置目录 /var/lib/mysql# mkdir undolog /var/lib/mysql# mv undo00* undolog/ 3:修改权限 /var/lib# chown -R mysql.mysql mysql/ 4:确定好目录没问题之后,就可以直接开启MySQL
如果MySQL已经正常启动,只需要执行start slave,不需要change就可以直接成为一个从服务。如果担心主从数据的一致性问题,可以通过主从一致性检验来保证。
2:增量备份的还原
上面已经模拟进行了周日全量备份,现在模拟在上面的全量基础上进行的增量备份。在进行全量备份时的LSN已经写入到了文件incremental_point.txt中,该文件和备份脚本在同一级目录。
还是和全量备份一样,执行上面给出的定制备份脚本,如执行时间是周二,执行完后备份服务器的目录如下:
# du -sch 2017-08-20/* 4.0K 2017-08-20/18.2G 2017-08-20/24.0K 2017-08-20/3 4.0K 2017-08-20/4 4.0K 2017-08-20/5 4.0K 2017-08-20/6 33G 2017-08-20/full_backup 41G total
可以看到增量备份目录是2,这里需要注意的是:真正的增量其实是对InnoDB的增量,而MyISAM和TokuDB还是直接拷贝文件的全量数据。可以通过增量备份打印出来的信息或则看增量备份的MyISAM、TokuDB的数据文件看出。
增量备份的备份流程和全量备份一样,可以直接看全量备份的说明即可,那么接着继续介绍如何进行增量+全量的还原。
因为通过上面的备份脚本已经把备份文件传输到了备份服务器B中,后面的相关操作只要在备份服务器B和MySQL服务器C中进行。
1)从备份服务器B中,把备份传到MySQL服务器C中。如备份目录为2
scp -r 2/ C:/data/dbbackup_dir/
2)在MySQL服务器C中进行解密、解压和prepare。解密的key需要和上面加密时候生成的key保持一致!解压需要安装qpress。
i ` . -iname `; /usr/local/xtrabackup_dir/bin/xbcrypt -d --encrypt-key-=/data/keyfile --encrypt-algo=AES256 < $i > $( $i)/$( $i .xbcrypt) && $i; f ` ./ -iname `; qpress -dT2 $f $( $f) && -f $f;
#prepare full_backup/usr/local/xtrabackup_dir/bin/xtrabackup --prepare --apply-log-only --use-memory=1G --target-dir=/data/dbbackup_dir/full_backup
这里需要注意全量备份的元数据中的信息(/data/dbbackup_dir):
# cat full_backup/xtrabackup_checkpoints backup_type = log-appliedfrom_lsn = 0to_lsn = 370623694056last_lsn = 370623694065compact = 0recover_binlog_info = 0# cat full_backup/xtrabackup_slave_info CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin-3306.000368', MASTER_LOG_POS=48441381;
基于全量备份的增量prepare,可以先删除全量备份目录下的ib_buffer_pool,不然会在prepare增量的时候报错,不过不影响后续操作。
xtrabackup: Can't create/write to file './ib_buffer_pool' (Errcode: 17 - File exists)[00] error: cannot open the destination stream for /ib_buffer_pool [00] Error: copy_file() failed.
接着应用增量备份
#prepare 2/usr/local/xtrabackup_dir/bin/xtrabackup --prepare --apply-log-only --use-memory=1G --target-dir=/data/dbbackup_dir/full_backup --incremental-dir=/data/dbbackup_dir/2
这里需要注意增量备份中元数据的信息(/data/dbbackup_dir),和全量备份中进行对比:
# cat 2/xtrabackup_checkpoints backup_type = incrementalfrom_lsn = 370623694056 #对应全量备份中的to_lsnto_lsn = 371913526149last_lsn = 371913526158compact = 0recover_binlog_info = 1# cat 2/xtrabackup_slave_infoCHANGE MASTER TO MASTER_LOG_FILE='mysql-bin-3306.000368', MASTER_LOG_POS=637921806; #对应的binlog不一样
在prepare增量备份期间,可以看到一些信息:
①:undolog会被增量追加,如:
xtrabackup: page size for /data/dbbackup_dir/2//undo001.delta is 16384 bytesApplying /data/dbbackup_dir/2//undo001.delta to ./undo001...
②:共享表空间被增量追加,如:
xtrabackup: page size for /data/dbbackup_dir/2//ibdata1.delta is 16384 bytesApplying /data/dbbackup_dir/2//ibdata1.delta to ./ibdata1...
③:ibd文件被增量追加,如:
xtrabackup: page size for /data/dbbackup_dir/2//test/test.ibd.delta is 16384 bytesApplying /data/dbbackup_dir/2//test/test.ibd.delta to ./test/test.ibd...
④:frm、MYI、MYD被全量复制,如:
170822 14:04:51 [01] Copying /data/dbbackup_dir/2/test/test.frm to ./test/test.frm170822 14:04:51 [01] ...done
⑤:没有看到TokuDB的增量和全量追加和复制,而且增量perpare完之后,全量备份里的tokudb文件被删除。
到这里增量备份已经prepare完成了,此时全量备份里的一些元数据文件已经被修改:
# cat full_backup/xtrabackup_checkpoints backup_type = full-preparedfrom_lsn = 0to_lsn = 371913526149 #已经把增量放进来了last_lsn = 371913526158compact = 0recover_binlog_info = 0# cat full_backup/xtrabackup_slave_infoCHANGE MASTER TO MASTER_LOG_FILE='mysql-bin-3306.000368', MASTER_LOG_POS=637921806; #更新成增量的信息
因为不支持TokuDB的增量,而且由于进行增量的prepare,导致全量备份里的tokudb文件被删除,所以需要手动进行复制TokuDB文件。从增量备份里复制tokudb相关的所有文件到全量备份,如:
/data/dbbackup_dir# /test
要是不确定那些库有TokuDB引擎,可以通过下面的命令来查看和复制,来替换mv xxx/*.tokudb
#在增量备份里执行/data/dbbackup_dir/2#for i in `find . -iname "*\.tokudb"`; do echo "mv $i ../full_backup/"$dirname $i; done | awk -F "/ ./" '{print $1"/"$2}'
最后再次prepare全量备份,生成redo log:
/usr/local/xtrabackup_dir/bin/xtrabackup --prepare --use-memory=1G --target-dir=/data/dbbackup_dir/full_backup
到此已经生成了还原所需要的所有文件,只需要把这些文件放到数据目录即可。
3)还原,复制文件
注意:备份和还原的MySQL配置文件所配置的目录需要保持一致,如:undolog是否独立,tokudb必须不能指定目录,保证备份和还原MySQL目录的一致性。如果起来当一个从来服务则需要修改server_id。
1:复制文件到数据目录 /data/dbbackup_dir# mv full_backup/* /var/lib/mysql/ 2:根据配置文件设置目录 /var/lib/mysql# mkdir undolog /var/lib/mysql# mv undo00* undolog/ 3:修改权限 /var/lib# chown -R mysql.mysql mysql/ 4:确定好目录没问题之后,就可以直接开启MySQL
如果MySQL已经正常启动,只需要执行start slave,不需要change就可以直接成为一个从服务。如果担心主从数据的一致性问题,可以通过主从一致性检验来保证。后续如果遇到什么“坑”,会持续更新。
补充
如何处理一张表的还原呢?因为XtraBackup是整个实例还原的,所以对于还原恢复单个表的操作可以这样操作(必须开启innodb_file_per_table),用下面的方法替换原有的prepare方法,只需要执行一次即可:
xtrabackup --prepare --export --target-dir=/data/dbbackup_dir/full_backup
用export方法,执行完后,数据库目录下的表文件格式会试这样:
test.cfg #包含了Innodb字典dumptest.exptest.frmtest.ibd
单表恢复还原:
1:先在MySQL里discard该表空间 mysql> alter table test discard tablespace;2:在备份目录里把需要的表文件复制到数据库目录下 上述的cfg、ibd、frm、exp的表文件复制过去 cp ... ...3:最后在MySQL里import该表空间 mysql> alter table test import tablespace;4:验证
总结
到此,关于XtraBackup的全量、增量备份还原已经介绍完,总的来说:想要进行物理备份并且有TokuDB引擎,官方的版本不支持,需要使用BohuTANG改版过的XtraBackup,兼容官方版本。并且主要注意下面的情况:
:尽量不要使用MyISAM,用InnoDB替换MyISAM,减少锁表时间。 :加密的keyfile必须要和解密的keyfile一致。
备份相关命令总结:
1:普通全量备份 xtrabackup --defaults-extra-file=/etc/mysql/uupp.cnf --datadir=/var/lib/mysql --host=172.16.109.132 --log-copy-interval=10 --no-timestamp --slave-info --safe-slave-backup --backup --parallel=5 --target-dir=/data/3306 2:压缩全量备份:qpress xtrabackup --defaults-extra-file=/etc/mysql/uupp.cnf --datadir=/var/lib/mysql --host=172.16.109.132 --log-copy-interval=10 --no-timestamp --slave-info --safe-slave-backup --backup --parallel=5 --compress --compress-threads=3 --target-dir=/data/3306 3:压缩加密全量备份 xtrabackup --defaults-extra-file=/etc/mysql/uupp.cnf --datadir=/var/lib/mysql --host=172.16.109.132 --log-copy-interval=10 --no-timestamp --slave-info --safe-slave-backup --backup --parallel=5 --compress --compress-threads=3 --encrypt=AES256 --encrypt-key-file=/data/keyfile --encrypt-threads=3 --target-dir=/data/3306 4:打包压缩加密全量备份: xtrabackup --defaults-extra-file=/etc/mysql/uupp.cnf --datadir=/var/lib/mysql --host=172.16.109.132 --log-copy-interval=10 --no-timestamp --slave-info --safe-slave-backup --backup --parallel=5 --compress --compress-threads=3 --stream=xbstream --encrypt=AES256 --encrypt-key-file=/data/keyfile --encrypt-threads=3 --target-dir=/data/3306/ > /data/3306/all_db.xbstream5:打包压缩加密传输到远程服务器,并在远程服务器解包 xtrabackup --defaults-extra-file=/etc/mysql/uupp.cnf --datadir=/var/lib/mysql --host=172.16.109.132 --log-copy-interval=10 --no-timestamp --slave-info --safe-slave-backup --backup --parallel=5 --compress --compress-threads=3 --stream=xbstream --encrypt=AES256 --encrypt-key-file=/data/keyfile --encrypt-threads=3 --target-dir=/data/3306/ | ssh 172.16.109.133 "xbstream -x -C /data/"#解包xbstream -x < all_db.xbstream #解密for i in `find . -iname "*\.xbcrypt"`; do /usr/local/xtrabackup_dir/bin/xbcrypt -d --encrypt-key-file=/data/keyfile --encrypt-algo=AES256 < $i > $(dirname $i)/$(basename $i .xbcrypt) && rm $i; done#解压for f in `find ./ -iname "*\.qp"`; do qpress -dT2 $f $(dirname $f) && rm -f $f; done #applyxtrabackup --prepare --apply-log-only --use-memory=1G --target-dir=/data/3306
参考文档
XtraBackup 使用说明
MySQL · TokuDB · 让Hot Backup更完美
TokuDB· HA方案·TokuDB热备