MySQL:亲测备份策略实例(线上真实备份案例)

小生博客:http://xsboke.blog.51cto.com

如果有疑问,请点击此处,然后发表评论交流,作者会及时回复(也可以直接在当前文章评论)。

                        -------谢谢您的参考,如有疑问,欢迎交流


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

说明:

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

一、服务器端配置

1、 Python编写的备份脚本

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

原文地址:https://blog.51cto.com/xsboke/2356678

时间: 2024-10-08 01:39:40

MySQL:亲测备份策略实例(线上真实备份案例)的相关文章

误删除线上无备份mongodb 1800万数据表的心路历程

2018-06-14 15:32 ,我误删除掉线上mongodb集群的表. ok,mongobooster是有stop按钮.点击停止救命一下.但是,根本停不掉,每刷新一下都能看到表单在1M递减的速度减少,每刷新一次 头晕就加重脑海飞速想解决方案 历程: 1.找运维,拿备份.  找了许久竟然没近期备份,最近的是五月初,我的天,我快倒在地上了. 2.竟然mongodb的collection是文件存储,那么靠运维磁盘中找到原来文件,400多G磁盘需要半小时检索.这半小时 ,看着异常不断增多,崩溃,每一

centos7下如何安装mysql 亲测

因为centos7 自带mariadb,所以第一步需要卸载mariadb 1.rpm -qa | grep mariadb  查看mariadb版本, 2.rpm -e --nodeps +版本  卸载mariadb mysql官网下载需要的版本 3.将mysql安装包解压到指定目录,命令如下: tar -zxvf mysql-5.7.18-linux-glibc2.5-x86_64.tar.gz -C /usr/local 4.进入/usr/local目录:cd /usr/local 5.为m

[亲测可用]ShopEx在Nginx上的的Rewrite伪静态规则

Nginx配置ShopEx伪静态其实最简单了.在规则里添加判断是否存在文件或者目录(!-e),然后将它转发给根目录下的index.php进行处理就好了. location / { if (!-e $request_filename) { rewrite ^/(.+\.(html|xml|json|htm|php|jsp|asp|shtml))$ /index.php?$1 last; } } 如果ShopEx放在其他目录中,只需要将"/"换成相对目录就可以了...例如放在shop文件夹

线上业务备份+定期删除备份文件+MD5加密

[[email protected] 192.168.1.20]# cat /server/scripts/beifen.sh #!/bin/shIP=$(ifconfig |awk -F '[ :]+' 'NR==2 {print $4}')Path="/backup/$IP"[ ! -d $Path ] && mkdir $Path -pMUBIAO="/app"#backuptar zcf $Path/www_$(date +%F).tar.g

grep线上环境精典案例后续

请执行命令取出 linux 中 eth0 的 IP 地址(请用 cut,有能力者也可分别用 awk,sed 命令答). 自己的方法: [[email protected]_back ~]# ifconfig eth0 eth0      Link encap:Ethernet  HWaddr 00:0C:29:21:B6:B1 inet addr:192.168.0.131  Bcast:192.168.0.255  Mask:255.255.255.0 inet6 addr: fe80::20

mysql常用的备份命令与备份策略

MySQL常用的备份命令 mysqldump备份常用方法: 1.导出一个数据库    mysqldump -u用户名 -p密码 数据库名 > 导出的文件名     例如      # mysqldump -hhostname -uroot -ppwd dataname >dataname.sql 2.备份服务器上所有数据库 例如       # mysqldump --all-databases > allbackupfile.sql  3.备份一个表 mysqldump -u用户名 -

记一次线上mysql主从架构异常的恢复经历

前提:之前一位同事负责的一位客户,因后期转到devops小组.所以将此用户交接给我,在后期发现有一套数据库主从环境,从库已经无法正常使用.查看slave 状态为: 其中:Master_Log_File:#此处显示的bin-log已经在master上找不见了Read_Master_Log_Pos:#显示的行数也就存在没有意义了Slave_IO_Running:NO #salve io进程显示为no,无法从master同步数据因此判定从库已经无法使用,需要及时修复.保证主从架构正常使用. 以下是恢复

MYSQL自动备份策略的选择与优劣点分析

目前流行几种备份方式:1.逻辑备份:使用mysql自带的mysqldump工具进行备份.备份成sql文件形式.优点:最大好处是能够与正在运行的mysql自动协同工作,在运行期间可以确保备份是当时的点,它会自动将对应操作的表锁定,不允许其他用户修改(只能访问).可能会阻止修改操作.sql文件通用方便移植.缺点:备份的速度比较慢.如果是数据量很多的时候.就很耗时间.如果数据库服务器处在提供给用户服务状态,在这段长时间操作过程中,意味着要锁定表(一般是读锁定,只能读不能写入数据).那么服务就会影响的.

MYSQL自动备份策略的选择与实践

目前流行几种备份方式: 1.逻辑备份:使用mysql自带的mysqldump工具进行备份.备份成sql文件形式.优点:最大好处是能够与正在运行的mysql自动协同工作,在运行期间可以确保备份是当时的点,它会自动将对应操作的表锁定,不允许其他用户修改(只能访问).可能会阻止修改操作.sql文件通用方便移植. 缺点:备份的速度比较慢.如果是数据量很多的时候.就很耗时间.如果数据库服务器处在提供给用户服务状态,在这段长时间操作过程中,意味着要锁定表(一般是读锁定,只能读不能写入数据).那么服务就会影响