MySQL如何使用使用Xtrabackup进行备份和恢复


Posted in MySQL onJune 21, 2021
目录
  • 1 备份
    • 1.1 全备
    • 1.2 增备
  • 2 备份恢复
    • 2.1 准备数据
    • 2.2 进行恢复
  • 3 目录结构
  • 4 备份脚本
    • 4.1 脚本
    • 4.2 配置文件
  • 5 恢复脚本
    • 5.1 脚本
    • 5.2 配置文件

 

1 备份

进行备份前需要先创建备份用户,直接使用 root 用户进行备份也行,但是这样不太规范。

create user backup@'localhost' identified by '123456';
    grant reload,process,lock tables,replication client on *.* to backup@localhost;

 

1.1 全备

备份整个库,使用的是备份用户,备份文件存放地址为 /backup/

innobackupex --defaults-file=/etc/my.cnf --user=backup --password=123456 /backup/

 

1.2 增备

指定为增量备分,使用的是备份用户,增量的基础为上一次的全备,已经使用 --incremental-basedir 进行指定了,备份后存放的文件为 /backup/

innobackupex --defaults-file=/etc/my.cnf --user=backup --password=123456 --incremental --incremental-basedir=/backup/2021-06-01_14-44-54 /backup/

 

2 备份恢复

 

2.1 准备数据

回滚未提交的事务及同步已经提交的事务至数据文件使数据文件处于一致性状态

innobackupex --apply-log --redo-only /backup/2021-06-01_14-44-54/

 

2.2 进行恢复

在恢复前,需要确保 MySQL 的数据目录为已经删除了。

innobackupex --copy-back --datadir=/usr/local/mysql/data /backup/2021-06-01_14-44-54/

恢复后,需要对 MySQL 的data 目录进行重新赋权:

chown -R mysql:mysql data/

到这恢复就完成了。

 

3 目录结构

MySQL如何使用使用Xtrabackup进行备份和恢复

 

4 备份脚本

 

4.1 脚本

backup.sh

#!/bin/bash
    # 获得程序路径名
    program_dir=`dirname $0`/..
    # 读取配置文件中的所有变量值, 设置为全局变量
    # 配置文件
    conf_file="$program_dir/conf/backup.conf"
    # mysql 用户
    user=`sed '/^user=/!d;s/.*=//' $conf_file`
    # mysql 密码
    password=`sed '/^password=/!d;s/.*=//' $conf_file`
    # mysql 备份目录
    backup_dir=`sed '/^backup_dir=/!d;s/.*=//' $conf_file`
    # mysql 备份压缩打包目录
    gzip_dir=`sed '/^gzip_dir=/!d;s/.*=//' $conf_file`
    # percona-xtrabackup命令xtrabackup路径
    xtrabackup_bin=`sed '/^xtrabackup_bin=/!d;s/.*=//' $conf_file`
    # mysql 全备前缀标识
    full_backup_prefix=`sed '/^full_backup_prefix=/!d;s/.*=//' $conf_file`
    # mysql 增量备前缀标识
    increment_prefix=`sed '/^increment_prefix=/!d;s/.*=//' $conf_file`
    # 备份错误日志文件
    error_log=$program_dir/var/`sed '/^error_log=/!d;s/.*=//' $conf_file`
    # 备份索引文件
    index_file=$program_dir/var/`sed '/^index_file=/!d;s/.*=//' $conf_file`
    # 备份日期
    backup_date=`date +%F`
    # 备份时间
    backup_time=`date +%H-%M-%S`
    # 备份时的周几
    backup_week_day=`date +%u`
    # 创建相关目录
    log_dir=$program_dir/log/backup
    var_dir=$program_dir/var
    mkdir -p $backup_dir
    mkdir -p $log_dir
    mkdir -p $var_dir
    mkdir -p $gzip_dir
    # 全量备份
    function full_backup() {
      backup_folder=${full_backup_prefix}_${backup_date}_${backup_time}_${backup_week_day}
      mkdir -p $backup_dir/$backup_folder
      $xtrabackup_bin \
        --user=$user \
        --password=$password \
        --backup \
        --target-dir=$backup_dir/$backup_folder > $log_dir/${backup_folder}.log 2>&1
      return $?
    }
    # 增量备份
    function increment_backup() {
      backup_folder=${increment_prefix}_${backup_date}_${backup_time}_${backup_week_day}
      incr_base_folder=`sed -n '$p' $index_file | \
                       awk -F '[, {}]*' '{print $3}' | \
                       awk -F ':' '{print $2}'`
      mkdir -p $backup_dir/$backup_folder
      $xtrabackup_bin \
        --user=$user \
        --password=$password \
        --backup \
        --target-dir=$backup_dir/$backup_folder \
        --incremental-basedir=$backup_dir/$incr_base_folder > $log_dir/${backup_folder}.log 2>&1
      return $?
    }
    # 删除之前的备份(一般在全备完成后使用)
    function delete_before_backup() {
      cat $index_file | awk -F '[, {}]*' '{print $3}' | \
        awk -v backup_dir=$backup_dir -F ':' '{if($2!=""){printf("rm -rf %s/%s\n", backup_dir, $2)}}' | \
        /bin/bash
      cat $index_file | awk -F '[, {}]*' '{print $3}' | \
        awk -v gzip_dir=$gzip_dir -F ':' '{if($2!=""){printf("rm -rf %s/%s\n", gzip_dir, $2)}}' | \
        /bin/bash
      cat $index_file | awk -F '[, {}]*' '{print $3}' | \
        awk -v log_dir=$log_dir -F ':' '{if($2!=""){printf("rm -rf %s/%s.log\n", log_dir, $2)}}' | \
        /bin/bash
    }
    # 备份索引文件
    function backup_index_file() {
      cp $index_file ${index_file}_$(date -d "1 day ago" +%F)
    }
    # 备份索引文件
    function send_index_file_to_remote() {
      # ./expect_scp ip地址 账号 密码  ${index_file} 目标服务器存放的文件夹 端口号 
      echo 'send index file ok'
    }
    # 添加索引, 索引记录了当前最新的备份
    function append_index_to_file() {
      echo "{week_day:$backup_week_day, \
             dir:${1}_${backup_date}_${backup_time}_${backup_week_day}, \
             type:${1}, \
             date:${backup_date}}" >> $index_file
    }
    # 记录错误消息到文件
    function logging_backup_err() {
      echo "{week_day:$backup_week_day, \
             dir:${1}_${backup_date}_${backup_time}_${backup_week_day}, \
             type:${1}, \
             date:${backup_date}}" >> $error_log
    }
    # 清空索引
    function purge_index_from_file() {
      > $index_file
    }
    # 清空错误日志信息
    function purge_err_log() {
      > $error_log
    }
    # 打包备份
    function tar_backup_file() {
      cd $backup_dir
      tar -jcf ${gzip_dir}/${1}_${backup_date}_${backup_time}_${backup_week_day}.tar.bz2 \
               ${1}_${backup_date}_${backup_time}_${backup_week_day}
      cd - > /dev/null
      rm -rf ${backup_dir}/${1}_${backup_date}_${backup_time}_${backup_week_day}
    }
    # 发送备份到远程
    function send_backup_to_remote() {
      #  ./expect_scp ip地址 账号 密码 ${gzip_dir}/${1}_${backup_date}_${backup_time}_${backup_week_day}.tar.bz2 目标服务器存放的文件夹 端口号 
      echo "send $1 remote ok"
    }
    # 判断是应该全备还是增量备份
    # 0:full, 1:incr
    function get_backup_type() {
      backup_type=0
      if [ 1 -eq `date +%H` ]; then
        backup_type=0
      else
        backup_type=1
      fi
      touch $index_file
      if [ ! -n "`cat $index_file`" ]; then
        backup_type=0
      fi
      return $backup_type
    }
    # 测试配置文件正确性
    function test_conf_file() {
      # 判断每个变量是否在配置文件中有配置,没有则退出程序
      if [ ! -n "$user" ]; then echo 'fail: configure file user not set'; exit 2; fi
      if [ ! -n "$password" ]; then echo 'fail: configure file password not set'; exit 2; fi
      if [ ! -n "$backup_dir" ]; then echo 'fail: configure file backup_dir not set'; exit 2; fi
      if [ ! -n "$gzip_dir" ]; then echo 'fail: configure file backup_dir not set'; exit 2; fi
      if [ ! -n "$full_backup_prefix" ]; then echo 'fail: configure file full_backup_prefix not set'; exit 2; fi
      if [ ! -n "$increment_prefix" ]; then echo 'fail: configure file increment_prefix not set'; exit 2; fi
      if [ ! -n "$error_log" ]; then echo 'fail: configure file error_log not set'; exit 2; fi
      if [ ! -n "$index_file" ]; then echo 'fail: configure file index_file not set'; exit 2; fi
    }
    # 执行
    function main() {
      # 检测配置文件值
      test_conf_file
      # 判断是执行全备还是增量备份
      get_backup_type
      backup_type=$?
      case $backup_type in
        0 )
          # 全量备份
          full_backup
          backup_ok=$?
          if [ 0 -eq "$backup_ok" ]; then
          # 全备成功
            # 打包最新备份
            tar_backup_file $full_backup_prefix
            # # 将tar备份发送到远程
            send_backup_to_remote $full_backup_prefix
            # 备份索引文件
            backup_index_file
            # 清除之前的备份
            delete_before_backup
            # 清除索引文件
            purge_index_from_file
            # 添加索引, 索引记录了当前最新的备份
            append_index_to_file $full_backup_prefix
            # 发送索引文件到远程
            send_index_file_to_remote
          else
          # 全备失败
            # 删除备份目录
            rm -rf ${backup_dir}/${full_backup_prefix}_${backup_date}_${backup_time}_${backup_week_day}
            # 记录错误日志
            logging_backup_err $full_backup_prefix
          fi
          ;;
        1 )
          # 增量备份
          increment_backup
          backup_ok=$?
          if [ "$backup_ok" -eq 0 ]; then
          # 增量备份成功
            # 打包最新备份
            tar_backup_file $increment_prefix
            # # 将tar备份发送到远程
            send_backup_to_remote $increment_prefix
            # 添加索引, 索引记录了当前最新的备份
            append_index_to_file $increment_prefix
            # # 发送索引文件到远程
            send_index_file_to_remote
          else
          # 增量备份失败
            # 删除备份目录
            rm -rf ${backup_dir}/${increment_prefix}_${backup_date}_${backup_time}_${backup_week_day}
            # 记录错误日志
            logging_backup_err $increment_prefix
          fi
          ;;
      esac
    }
    main

 

4.2 配置文件

backup.conf

# mysql 用户名
    user=backup
    # mysql 密码
    password=123456
    # 备份路径
    backup_dir=/data/backup
    # 备份压缩打包目录
    gzip_dir=/data/backups/backups_zip
    # innobackupex 命令路径
    xtrabackup_bin=/opt/xtrabackup/bin/xtrabackup
    # 全量备信息名称 前缀
    full_backup_prefix=full
    # 增量备信息名称 前缀
    increment_prefix=incr
    # 错误日志文件(根据此文件知道备份是否成功)
    # format:
    # {week_day:1,dir:full/incr_2015-12-29_00-00-00_7,type:full/incr,date:2015-12-30}
    error_log=mysql_increment_hot_backup.err
    # 索引文件
    # format:
    # {week_day:1,dir:full/incr_2015-12-29_00-00-00_7,type:full/incr,date:2015-12-30}
    index_file=mysql_increment_hot_backup.index

 

5 恢复脚本

 

5.1 脚本

restore.sh

#!/bin/bash
    # 获得程序路径名
    program_dir=`dirname $0`/..
    # 读取配置文件中的所有变量值, 设置为全局变量
    # 配置文件
    conf_file="$program_dir/conf/restore.conf"
    # MySQL 数据文件夹
    data_dir=`sed '/^data_dir=/!d;s/.*=//' $conf_file`
    # 备份索引文件路径
    backup_index_file=`sed '/^backup_index_file=/!d;s/.*=//' $conf_file`
    # percona-xtrabackup命令xtrabackup路径
    xtrabackup_bin=`sed '/^xtrabackup_bin=/!d;s/.*=//' $conf_file`
    # 备份文件目录
    backup_restore_dir=`sed '/^backup_restore_dir=/!d;s/.*=//' $conf_file`
    # 检查配置文件正确性
    function exam_conf_file() {
        # 判断每个变量是否在配置文件中有配置,没有则退出程序
        if [ ! -n "$data_dir" ]; then echo 'fail: configure file data_dir not set'; exit 2; fi
        if [ ! -n "$backup_index_file" ]; then echo 'fail: configure file backup_index_file not set'; exit 2; fi
        if [ ! -n "$xtrabackup_bin" ]; then echo 'fail: configure file xtrabackup_bin not set'; exit 2; fi
        if [ ! -n "$backup_restore_dir" ]; then echo 'fail: configure file backup_restore_dir not set'; exit 2; fi
    }
    # 检查备份文件是否是压缩格式
    function exam_backup_restore_file(){
        file_backup_restore_name_arr=`ls $backup_restore_dir`
        for file_name in $file_backup_restore_name_arr;do
            if [ "${file_name##*.}"x = "bz2"x ];then
                tar -jxf $backup_restore_dir/$file_name -C $backup_restore_dir
                rm -rf $backup_restore_dir/$file_name
            fi

        done
    }
    # 检查 MySQL 是否停止
    function exam_mysql_is_stop(){
        if [ 0 -eq `ps -ef | grep mysql | grep -v grep | wc -l` ]; then
            echo "MySQL 服务已停止"
        else
            /etc/init.d/mysqld stop
            echo "正在停止 MySQL 服务"
            sleep 3
            echo "已停止 MySQL 服务"
        fi
    }
    # 检查 MySQL data 文件是否删除
    function exam_data_is_del(){
        if [ -d $data_dir ];then
            echo "正在删除 MySQL 的data文件"
            rm -rf $data_dir
        else
            echo "MySQL 的数据文件已删除 "
        fi
    }
    # 读取备份索引文件
    function read_backup_index() {
        cat $backup_index_file | awk '{print $2}' | awk -F: '{print $2}' | awk '{sub(/.$/,"")}1'
    }
    # 准备全备文件
    function ready_full(){
        full_file_name=`echo ${1} | awk '{print $1}'`
        $xtrabackup_bin/innobackupex \
            --apply-log \
            --redo-only \
            $backup_restore_dir/$full_file_name

        echo "全备文件已准备好"
    }
    # 准备增备文件
    function ready_incr(){
        backup_index=$(read_backup_index)
        full_file_name=`echo $backup_index | awk '{print $1}'`
        for file_name in $backup_index;do
            if [ 1 -eq `echo "$file_name" | grep incr | wc -l` ]; then 
                $xtrabackup_bin/innobackupex \
                    --apply-log \
                    --redo-only \
                    $backup_restore_dir/$full_file_name \
                    --incremental-dir=$backup_restore_dir/$file_name
            fi
        done
        echo "增备文件已准备好"
    }
    # 执行备份恢复
    function exec_backup_restore(){
        echo "开始进行备份恢复"
        full_file_name=`echo ${1} | awk '{print $1}' `
        $xtrabackup_bin/innobackupex \
            --copy-back \
            --datadir=$data_dir \
            $backup_restore_dir/$full_file_name
    }
    # 执行
    function main() {
        # 检查配置文件正确性
        exam_conf_file
        # 检查备份文件是否是压缩格式
        exam_backup_restore_file
        # 检查 MySQL 是否停止
        exam_mysql_is_stop
        # 检查 MySQL data 文件是否删除
        exam_data_is_del
        # 读取索引文件
        backup_index=$(read_backup_index)
        # 准备全备文件
        ready_full $backup_index
        # 准备增备文件
        ready_incr
        # 执行备份恢复
        exec_backup_restore $backup_index
        # 对数据文件进行赋权
        echo "重新对数据目录赋权"
        chown -R mysql:mysql $data_dir
        echo "正在启动MySQL"
        /etc/init.d/mysqld start
        echo "备份恢复成功"
    }
    main

 

5.2 配置文件

restore.conf

# MySQL 数据文件夹
    data_dir=/opt/mysql/data
    #备份索引文件路径
    backup_index_file=/opt/xtrabackup/backup/var/mysql_increment_hot_backup.index
    #xtrabackup bin 的目录 
    xtrabackup_bin=/opt/xtrabackup/bin
    # 备份文件目录
    backup_restore_dir=/data/backups/backups_zip

以上就是MySQL如何使用使用Xtrabackup进行备份和恢复的详细内容,更多关于MySQL 用Xtrabackup备份和恢复的资料请关注三水点靠木其它相关文章!

MySQL 相关文章推荐
Mysql - 常用函数 每天积极向上
Apr 05 MySQL
如何使用Maxwell实时同步mysql数据
Apr 08 MySQL
详细谈谈MYSQL中的COLLATE是什么
Jun 11 MySQL
低版本Druid连接池+MySQL驱动8.0导致线程阻塞、性能受限
Jul 01 MySQL
基于MySql验证的vsftpd虚拟用户
Nov 07 MySQL
SQL 聚合、分组和排序
Nov 11 MySQL
全面盘点MySQL中的那些重要日志文件
Nov 27 MySQL
mysql insert 存在即不插入语法说明
Mar 25 MySQL
Mysql查询时间区间日期列表,不会由于数据表数据影响
Apr 19 MySQL
MySQL 数据库范式化设计理论
Apr 22 MySQL
MySQL选择合适的备份策略和备份工具
Jun 01 MySQL
MySQL外键约束(Foreign Key)案例详解
Jun 28 MySQL
MySQL 数据恢复的多种方法汇总
Jun 21 #MySQL
Mysql数据库值的添加、修改、删除及清空操作实例
Unity连接MySQL并读取表格数据的实现代码
新手入门Mysql--sql执行过程
MySQL 外键约束和表关系相关总结
Jun 20 #MySQL
MySQL 使用索引扫描进行排序
Jun 20 #MySQL
新手入门Mysql--概念
You might like
php生成缩略图的类代码
2008/10/02 PHP
php 归并排序 数组交集
2011/05/10 PHP
php制作动态随机验证码
2015/02/12 PHP
PHP递归遍历指定文件夹内的文件实现方法
2016/11/15 PHP
Laravel自定义 封装便捷返回Json数据格式的引用方法
2019/09/29 PHP
jquery focus(fn),blur(fn)方法实例代码
2011/12/16 Javascript
Javascript对象中关于setTimeout和setInterval的this介绍
2012/07/21 Javascript
JS获取网页属性包括宽、高等等
2014/04/03 Javascript
js+canvas简单绘制圆圈的方法
2016/01/28 Javascript
深入探讨Vue.js组件和组件通信
2016/09/12 Javascript
常用JS图片滚动(无缝、平滑、上下左右滚动)代码大全(推荐)
2016/12/20 Javascript
JS实现身份证输入框的输入效果
2017/08/21 Javascript
JavaScript基础之流程控制语句的用法
2017/08/31 Javascript
JQuery 又谈ajax局部刷新
2017/11/27 jQuery
解决vue中虚拟dom,无法实时更新的问题
2018/09/15 Javascript
让webpack+vue-cil项目不再自动打开浏览器的方法
2018/09/27 Javascript
javascript自定义加载loading效果
2020/09/15 Javascript
Python对两个有序列表进行合并和排序的例子
2014/06/13 Python
浅析python3中的os.path.dirname(__file__)的使用
2018/08/30 Python
numpy.random.shuffle打乱顺序函数的实现
2019/09/10 Python
Django 解决distinct无法去除重复数据的问题
2020/05/20 Python
python破解同事的压缩包密码
2020/10/14 Python
如何基于python实现年会抽奖工具
2020/10/20 Python
奥地利婴儿用品和玩具购物网站:baby-markt.at
2020/01/26 全球购物
Linux开机引导的步骤是什么
2015/10/19 面试题
中专生职业生涯规划书范文
2013/12/29 职场文书
物控部经理职务说明书
2014/02/25 职场文书
机电一体化专业求职信
2014/07/22 职场文书
庆元旦演讲稿
2014/09/15 职场文书
大学生实训报告总结
2014/11/05 职场文书
初中班主任工作总结2015
2015/05/13 职场文书
2016年员工年度考核评语
2015/12/02 职场文书
演讲稿之开卷有益
2019/08/07 职场文书
nginx location优先级的深入讲解
2021/03/31 Servers
铁头也玩根德 YachtBoy YB-230......
2022/04/05 无线电
Java 通过手写分布式雪花SnowFlake生成ID方法详解
2022/04/07 Java/Android