XtraBackup应用说明(支持TokuDB) XtraBackup 安装使用 XtraBackup 使用说明

背景:

      关于物理备份工具xtrabackup的一些说明能够先看以前写过的文章说明:XtraBackup 安装使用xtrabackup 使用说明(续),本篇文章将介绍xtrabackup在使用中的注意事项和如何全量、增量备份和恢复,包含TokuDB的备份(感谢吴总的推荐)。因为物理备份消耗的空间比较大,因此在工做中一直使用mydumper进行备份,经过逻辑备份虽然空间使用上又很大改善,可是因为还原的时候须要消耗很长时间才能使用,也很是使人头疼。如今准备在生产环境中使用XtraBackup,记录使用中的一些注意事项。
php

安装:

环境:html

XtraBackup版本为:2.4
系统版本:14.0416.04
MySQL版本:5.7.16

说明:由于生产环境中有使用到TokuDB引擎,而Percona版本的XtraBackup不支持对TokuDB的备份,因此不能使用官方的版本。不过有人基于官方版本进行了修改,支持Tokudb的备份,下载地址:https://github.com/XeLabs/tokudb-xtrabackup,做者是BohuTANG。编译安装过程python

① 下载:mysql

git clone https://github.com/XeLabs/tokudb-xtrabackup.git

② 安装依赖包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

③ 编译安装github

#程序目录
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=1

make -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进行剥离:sql

strip xtrabackup 

备份使用说明:

限制shell

对于上面编译好的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 24

echo -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 os
import sys
import time
import datetime
import smtplib
import subprocess
import re
import MySQLdb

from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.Utils import COMMASPACE, formatdate

reload(sys)
sys.setdefaultencoding('utf8')

RETRIES = 1

def 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_times
def 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,weekday

def getMonDay(num):
    monday = (datetime.date.today() - datetime.timedelta(days=num)).strftime("%Y-%m-%d")
    return monday

def getTime():
    now = datetime.datetime.now().strftime('%H:%M:%S')
    return now

def getPath():
    Path = os.path.realpath(os.path.dirname(__file__))
    return Path

def 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_str

if __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 = ['zjy@dxyer.com']
                send_mail(mail_list, subject.encode("utf8"), 'Sucess!', "XtraBackup@smtp.dxy.cn", server="smtp.host.dxy")
            else :
                subject = '%s【%s】全量物理备份获取lsn失败' %(today,instance_name)
                mail_list = ['zjy@dxyer.com']
                send_mail(mail_list, subject.encode("utf8"), res, "XtraBackup@smtp.dxy.cn", server="smtp.host.dxy")
        else :
            subject = '%s【%s】全量物理备份失败' %(today,instance_name)
            mail_list = ['zjy@dxyer.com']
            send_mail(mail_list, subject.encode("utf8"), res, "XtraBackup@smtp.dxy.cn", 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 = ['zjy@dxyer.com']
                send_mail(mail_list, subject.encode("utf8"), 'Sucess!', "XtraBackup@smtp.dxy.cn", server="smtp.host.dxy")
            else :
                subject = '%s【%s】增量物理备份失败' %(today,instance_name)
                mail_list = ['zjy@dxyer.com']
                send_mail(mail_list, subject.encode("utf8"), res, "XtraBackup@smtp.dxy.cn", 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 = ['zjy@dxyer.com']
                send_mail(mail_list, subject.encode("utf8"), str(e) , "XtraBackup@smtp.dxy.cn", server="smtp.host.dxy")
View Code

备份服务器B上的脚本:

#!/usr/bin/env python
#-*- encoding:utf-8 -*-
import os
import sys
import time
import datetime
import commands

def getDate():
    today = datetime.datetime.now().strftime('%Y-%m-%d')
    weekday = datetime.datetime.now().weekday()
    return today,weekday

def 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 "只在周日执行..."
View Code

模拟全量备份,备份流程原理的信息以下:

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 BACKUP
1.禁止非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和redo
9):记录LSN最后的点,中止redo log的线程的备份
10):解锁binlog和tables
11):开始和完成备份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_backup
33G    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/1
8.2G 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_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。

#解密:在full_backup和2目录里执行
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

#解压:在full_backup和2目录里执行
for f in `find ./ -iname "*\.qp"`; do qpress -dT2 $f  $(dirname $f) && rm -f $f; done 
#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-applied
from_lsn = 0 to_lsn = 370623694056
last_lsn = 370623694065
compact = 0
recover_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 = incremental
from_lsn = 370623694056 #对应全量备份中的to_lsn to_lsn = 371913526149
last_lsn = 371913526158
compact = 0
recover_binlog_info = 1

# cat 2/xtrabackup_slave_info
CHANGE 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 bytes
Applying /data/dbbackup_dir/2//undo001.delta to ./undo001...

②:共享表空间被增量追加,如:

xtrabackup: page size for /data/dbbackup_dir/2//ibdata1.delta is 16384 bytes
Applying /data/dbbackup_dir/2//ibdata1.delta to ./ibdata1...

③:ibd文件被增量追加,如:

xtrabackup: page size for /data/dbbackup_dir/2//test/test.ibd.delta is 16384 bytes
Applying /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.frm
170822 14:04:51 [01]        ...done

⑤:没有看到TokuDB的增量和全量追加和复制,并且增量perpare完以后,全量备份里的tokudb文件被删除。

到这里增量备份已经prepare完成了,此时全量备份里的一些元数据文件已经被修改:

# cat full_backup/xtrabackup_checkpoints 
backup_type = full-prepared
from_lsn = 0 to_lsn = 371913526149 #已经把增量放进来了
last_lsn = 371913526158
compact = 0
recover_binlog_info = 0

# cat full_backup/xtrabackup_slave_info
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin-3306.000368', MASTER_LOG_POS=637921806; #更新成增量的信息

由于不支持TokuDB的增量,并且因为进行增量的prepare,致使全量备份里的tokudb文件被删除,因此须要手动进行复制TokuDB文件。从增量备份里复制tokudb相关的全部文件到全量备份,如:

/data/dbbackup_dir# mv 2/test/*tokudb full_backup/test/
/data/dbbackup_dir# mv 2/tokudb_log/* full_backup/tokudb_log/ /data/dbbackup_dir# mv 2/tokudb.directory full_backup/ /data/dbbackup_dir# mv 2/tokudb.environment full_backup/ /data/dbbackup_dir# mv 2/__tokudb_lock_dont_delete_me_data full_backup/ /data/dbbackup_dir# mv 2/tokudb.rollback full_backup/

要是不肯定那些库有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字典dump
test.exp
test.frm
test.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,兼容官方版本。而且主要注意下面的状况:

1:不能设置tokudb_data_dir;
2:不能自动的增量备份TokuDB,须要手动的复制Tokudb文件。
3:备份和还原的MySQL大版本保持一致,并且设置目录的参数也要同样。
4:尽可能不要使用MyISAM,用InnoDB替换MyISAM,减小锁表时间。
5:加密的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.xbstream

5:打包压缩加密传输到远程服务器,并在远程服务器解包
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 

#apply
xtrabackup --prepare --apply-log-only --use-memory=1G --target-dir=/data/3306
View Code 

参考文档

XtraBackup 使用说明

MySQL · TokuDB · 让Hot Backup更完美

TokuDB· HA方案·TokuDB热备

相关文章
相关标签/搜索