温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

MySQL亲测备份策略真实案例详讲

发布时间:2020-04-29 11:45:32 来源:亿速云 阅读:242 作者:三月 栏目:MySQL数据库

下文主要给大家带来MySQL亲测备份策略真实案例详讲,希望这些文字能够带给大家实际用处,这也是我编辑这篇文章的主要目的。好了,废话不多说,大家直接看下文吧。


是否为线上库的备份而烦恼过,这里提供一个完整的备份从属数据库的备份方案,亲测可用

说明:

  1. 备份从库,按周计,每周进行一次全备
  2. 每周一的早上六点进行全备,其他时间备份中继日志
  3. 在从库上启用rsync服务,用于异地备份
  4. 在本地云服务器使用rsync命令定时同步数据库的备份
  5. 此备份可用于为Master添加新的Slave,也可以用于还原Master

一、服务器端配置

1、 Python编写的备份脚本

MySQL亲测备份策略真实案例详讲

root@DBSlave:~# cat /scripts/mysql_slave_backup.py #!/usr/bin/env python #-*- coding:utf-8 -*- import os import datetime,time # 请在linux系统中安装zip和unzip # 备份策略示例 '''    1. 每周进行一次全备,其他都是备份中继日志    2. 每周一凌晨6:00数据库全备份    3. 周二至周日,每天中午12:00,下午18:00,早上6:00,备份中继日志 ''' # 规划备份目录 # 备份目录以周为单位进行创建 # "%W":一年中的第几周,以周一为每星期第一天(00-53) Date_Time = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")   #  %F:年月日 Week_Date = datetime.datetime.now().strftime("%Y-%W")     # 年/当前是本年的第几周 Dir = "/data/backup" Backup_Dir = Dir+ '/' + Week_Date # -- 创建备份目录  ,每周生成一个目录,因为每周做一次全备 if os.path.isdir(Backup_Dir) is False:    os.makedirs(Backup_Dir) # 设置数据库连接信息 #mysqldump选项 #    --skip-tz-utc                : 保持和表导出前的时区是一样的 #    --master-data=2              : 备份时写入"change master to"语句并且注释,等于1时,则不会注释 #    --dump-slave=2               : 备份slave的数据库,为master新增slave时使用. #    --quick                      : 一次从行中的服务器检索表的行,作用是加快导出表 #    --routines                   : 导出存储过程 #    --triggers                   : 导出触发器 #    --set-gtid-purged=OFF        : 防止备份数据导入新的实例时与其GTID发生冲突,所以在备份数据时不添加GTID信息 #    --single-transaction         : 在从服务器转储数据之前发出BEGIN SQL语句,尽量保证数据的一致性,但是这个参数只适用于innodb这样的存储引擎 #    --dump-slave=2               : 备份时写入从库连接主库的change语句并且注释,等于1时,则不会注释 # 设置数据库备份信息 DB = '-uroot -p123456'  # 指定登录账号和密码 ARG = '--dump-slave=2 --skip-tz-utc --routines --triggers --quick --default-character-set=utf8 --single-transaction'    # 指定备份参数 DB_NAME = "dbname"  # 数据库名称 Back_DBNAME = DB_NAME + '_' + Date_Time + '.sql'    # 数据库备份名称 Logs_File = Backup_Dir + '/logs'    # 指定备份时日志输出的文件 Mysql_Bin = "/usr/bin/mysql"    # 指定[mysql]命令所在路径 MysqlDump_Bin = "/usr/bin/mysqldump"    # 指定[mysqldump]命令所在路径 Relay_Log_Dir = "/data/logs/relay_log"  #指定中继日志 Relay_Log_Info = "/data/logs/relay_log/relay-bin.info"  # 用于获取当前正在使用的中继日志 # 定义删除旧备份 def Del_Old():    '''删除36天前的旧备份'''    OLD_Files = os.popen("find %s -type f  -mtime +36"%(Dir)).readlines()    if len(OLD_Files) > 0:        for OLD_FIle in OLD_Files:            FileName = OLD_FIle.split("\n")[0]            os.system("rm -f %s"%(FileName))    # 删除空目录    All_Dir = os.popen("find %s -type d"%(Dir + '/*')).readlines()    for Path_Dir in All_Dir:        Path_Dir = Path_Dir.split("\n")[0]        Terms = os.popen("ls %s | wc -l"%(Path_Dir)).read()        if int(Terms) == 0:            os.system("rm -rf %s"%(Path_Dir)) # 备份已经同步完成的中继日志文件 def ZIP_And_Del_Existed():    '''    压缩已经同步完成的日志文件并删除,    为防止中继日志还没有同步完成,就被删除,这里作一个判断,只压缩和删除已经同步过的中继日志    '''    # 获取所有的中继日志    Relog_List = os.popen("ls %s | grep \"^relay-bin.*\" | grep -v \"relay-bin.in*\"" % (Relay_Log_Dir)).readlines()    # 获取当前正在使用的中继日志文件    CurRelay = os.popen("cat %s | head -n 1" % (Relay_Log_Info)).readline().split("\n")[0]    CurRelay_MTime = os.path.getmtime(CurRelay)  # 获取当前正在使用的文件的最后修改时间    # 循环所有的中继日志文件,通过和中继日志的最后修改时间进行对比,得到需要备份的中继日志    Need_ZIP_FName = []  # 定义需要压缩和删除的文件名    for FileName in Relog_List:        '''        将修改时间小于[当前正在使用的中继日志]文件的文件,加入到 列表 [Need_ZIP_FName] 中,用于备份/删除.        '''        FName =  FileName.split("\n")[0]        FName_MTime = os.path.getmtime("%s/%s"%(Relay_Log_Dir,FName))        if FName_MTime < CurRelay_MTime:            Need_ZIP_FName.append("%s/%s"%(Relay_Log_Dir,FName))    os.system("zip -j %s/Relay_log_%s.zip %s" % (Backup_Dir, Date_Time," ".join(Need_ZIP_FName)))    # 获取已经压缩的中继日志文件,然后删除    for Relay_Log in Need_ZIP_FName:        os.system("rm -f %s"%(Relay_Log)) # 开始执行备份.(判断,如果今天是星期一则进行全备,不是星期一则增量备份) IF_Week = datetime.datetime.now().strftime('%w') if int(IF_Week) == 1:    # 匹配是否已经存在全备    Test = os.popen('ls %s | grep -E \"^%s.*([0-9]{2}-[0-9]{2}-[0-9]{2}).sql.zip\" | wc -l'%(Backup_Dir,DB_NAME)).readline()    if int(Test) == 0:        # 如果星期一已经进行全备,则开始增量备份        with open(Logs_File,'a+') as file:            file.writelines("####----------        分界线        ----------####\n")            file.writelines("###start    >>>全备    datetime : %s\n"%(datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")))            file.writelines("###     今天是周%s\n"%(IF_Week))            file.writelines("###     stop slave\n")            os.system("%s %s -e \"stop slave\""%(Mysql_Bin,DB))            file.writelines("###     status slave\n")            Show_Slave = os.popen("%s %s -e \"show slave status\G\""%(Mysql_Bin,DB)).readlines()            file.writelines(Show_Slave)            file.writelines("###     backup\n")            os.system("%s %s %s %s > %s/%s"%(MysqlDump_Bin,DB,ARG,DB_NAME,Backup_Dir,Back_DBNAME))            file.writelines("###    backup done && start slave | datetime : %s\n"%(datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")))            os.system("%s %s -e \"start slave;\""%(Mysql_Bin,DB))            time.sleep(5)            file.writelines("###    slave status\n")            Show_Slave = os.popen("%s %s -e \"show slave status\G\"" % (Mysql_Bin, DB)).readlines()            file.writelines(Show_Slave)            file.writelines("###done    >>>全备完成\n")            os.system("zip -j %s/%s.zip %s/%s"%(Backup_Dir,Back_DBNAME,Backup_Dir,Back_DBNAME))            os.system("rm %s/%s"%(Backup_Dir,Back_DBNAME))            file.writelines("\n\n\n\n\n")        Del_Old()    else:        with open(Logs_File,'a+') as file:            file.writelines("####----------        分界线        ----------####\n")            file.writelines("###start    >>>增量备份    datetime : %s\n"%(datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")))            file.writelines("###     今天是周%s\n"%(IF_Week))            file.writelines("###     stop slave\n")            os.system("%s %s -e \"stop slave\""%(Mysql_Bin,DB))            file.writelines("###     status slave\n")            Show_Slave = os.popen("%s %s -e \"show slave status\G\""%(Mysql_Bin,DB)).readlines()            file.writelines(Show_Slave)            file.writelines("###     backup\n")            ZIP_And_Del_Existed()            file.writelines("###    backup done && start slave | datetime : %s\n"%(datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")))            os.system("%s %s -e \"start slave;\""%(Mysql_Bin,DB))            time.sleep(5)            file.writelines("###    slave status\n")            Show_Slave = os.popen("%s %s -e \"show slave status\G\"" % (Mysql_Bin, DB)).readlines()            file.writelines(Show_Slave)            file.writelines("###done    >>>增量备份完成\n")            file.writelines("\n\n\n\n\n")        Del_Old() else:    with open(Logs_File, 'a+') as file:        file.writelines("####----------        分界线        ----------####\n")        file.writelines("###start    >>>增量备份    datetime : %s\n" % (datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")))        file.writelines("###     今天是周%s\n" % (IF_Week))        file.writelines("###     stop slave\n")        os.system("%s %s -e \"stop slave\"" % (Mysql_Bin, DB))        file.writelines("###     status slave\n")        Show_Slave = os.popen("%s %s -e \"show slave status\G\"" % (Mysql_Bin, DB)).readlines()        file.writelines(Show_Slave)        file.writelines("###     backup\n")        ZIP_And_Del_Existed()        file.writelines("###    backup done && start slave | datetime : %s\n" % (datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")))        os.system("%s %s -e \"start slave;\"" % (Mysql_Bin, DB))        time.sleep(5)        file.writelines("###    slave status\n")        Show_Slave = os.popen("%s %s -e \"show slave status\G\"" % (Mysql_Bin, DB)).readlines()        file.writelines(Show_Slave)        file.writelines("###done    >>>增量备份完成\n")        file.writelines("\n\n\n\n\n")    Del_Old()

2、计划任务

root@DBSlave:~# cat /etc/cron.d/general #mysql backup 0 6     * * *   root    python /scripts/mysql_slave_backup.py 0 12    * * *   root    python /scripts/mysql_slave_backup.py 0 18    * * *   root    python /scripts/mysql_slave_backup.py

3、rsync配置

root@DBSlave:~# cat /etc/rsyncd.conf uid = 0 gid = 0 use chroot = yes address = "当前主机公网地址" port = 8638 log file = /var/log/rsync.log pid file = /var/run/rsync.pid hosts allow = "只允许某个IP连接" [databases] path = /data/backup/ comment = databases read only = yes dont compress = *.gz *.bz2 *.zip # 只允许remoteuser用户 auth users = remoteuser secrets file = /etc/rsyncd_users.db
root@DBSlave:~# cat /etc/rsyncd_users.db # 格式: 用户名:密码 remoteuser:password

二、 本地备份主机配置

1、创建rsync密码文件

root@localhost:~# cat /etc/server.pass remoteuser:password

2、 同步脚本

root@localhost:~# cat /scripts/backup.sh #!/bin/bash SSH=$(which ssh) Logs_Dir="/Backup/logs.txt" Rsync=$(which rsync) Project="databases" Dest="/Backup/" IF_DEL_FILE=$(find ${Dest} -type f -mtime +36 -name "*" | wc -l) DEL_FILE=$(find ${Dest} -type f -mtime +36 -name "*") # 删除旧备份 RMOLD(){    if [ "${IF_DEL_FILE}" -gt "0" ]    then        for filename in ${DEL_FILE}        do            rm -f ${filename}        done        rmdir ${Dest}*  # 删除空目录    fi } # 执行同步命令 Backup(){    echo "###    ---------- datetime : `date +%F-%H-%M-%S` ----------    ###" >> ${Logs_Dir}    echo "#    start rsync" >> ${Logs_Dir}    ${Rsync} -azH --password-file=/etc/server.pass --bwlimit=300 --port=8638 remoteuser@数据库rsync监听的IP地址::${Project} ${Dest} &>> ${Logs_Dir}    echo "###    end   rsync    ---------- dateime : `date +%F-%H-%M-%S` ----------    ###" >> ${Logs_Dir}    echo -e "\n\n\n\n\n" >> ${Logs_Dir}    RMOLD } # 判断如果当前正在同步则不再执行同步命令 IFProcess(){    ps -ef | grep "${Rsync} -azH --password-file=/etc/server.pass --bwlimit=300 --port=8638 remoteuser@数据库rsync监听的IP地址::${Project}" | grep -v "grep" &> /dev/null    if [[ "$?" == 0 ]]    then        exit 0    else        Backup    fi } IFProcess

3、计划任务

root@localhost:~# cat /etc/cron.d/general

01 23 * * * root /bin/sh /scripts/backup.sh

对于以上关于MySQL亲测备份策略真实案例详讲,大家是不是觉得非常有帮助。如果需要了解更多内容,请继续关注我们的行业资讯,相信你会喜欢上这些内容的。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI