数据库回档操作

发布时间 2023-07-23 15:26:26作者: 天庭保安猪八戒

要求:模仿腾讯云数据库,选择数据库,或者数据库下的表,然后点击回档时间,进行回档操作;

实现:实现思路通过 冷备数据+热备数据 实现数据库回档到固定的时间点,前提要求,数据库固定时间都会进行数据备份;

冷备数据:冷备方式有多种,物理冷备,逻辑冷备;

  物理冷备:就是把数据库整个文件拷贝下来,需要的时候直接粘到我们的数据库目录下(只适用于MYISAM数据引擎,并且数据库大版本不同,数据库下目录结构不同),也可以通过第三方软件进行备份;

  逻辑备份:使用mysq自带的命令mysqldump命令,进行备份,会导出sql文件,可以跨版本,灵活,如下,将test数据库,导出,back.sql,back前面的是当前时间,

-F表示备份后刷新binlog日志(这里刷新的原因是,冷备数据有了,恢复时就不需要之前的binlog了,重置新的binlog日志),--source-data,表示在备份的sql文件中要记录备份后的binlog日志版本,还有结束位点(很有必要);该命令需要在操作系统中执行,不能进mysql中;
       mysqldump -uroot -pzzyy55555 -B -F -R -x --source-data test > $(date +%F%T)back.sql;
热备数据:mysql的binlog日志,该日志mysql8自动开启,show variables like '%log_bin%',mysql数据库中使用该命令可以查看binlog是否开启

  binlog日志是以二进制格式存放的,必须使用mysqldump命令查看才能看见,mysql-bin.index,前缀名可能不一样,index结尾的文件,会实时更新,里面记录的是所有二进制文件的名字,并且当二进制文件更新时,它就会更新,默认一个G,超过也会自动更新。

  SHOW BINARY LOGS; mysql中使用该命令,可以查看所有的binlog日志,file_size,表示最后一个事件的位点;

  SHOW MASTER STATUS;该命令可以查看出当面mysql使用的binlog日志,因为每当数据库重启一次,binlog日志都会自增一个;或者使用flush logs,也可以手动刷新日志,我们恢复备份时手动执行一下该命令,不然恢复记录也会记录进入binlog日志中,不刷新的话,数据库日志会十分混乱;

真正实现:上面介绍了我们需要使用的冷备,热备数据,接下来是具体的恢复方案,参考其它播客,选择的方式如下图,就是需要一个主机用来做备份主机,将数据回档到目标时间后,拿到我们需要的目标库表,进行数据倒灌,最终实现数据回档;

  ①目标数据库需要定时执行备份,这是备份所有数据库,mysqldump -uroot -pzzyy55555 --all –databases -F -R -x --source-data > $(date +%F%T)back.sql,这个是备份指定数据库:mysqldump -uroot -pzzyy55555 -B -F -R -x --source-data test |gzip >test$(date +%F%T).sql;

 备份的sql中,在开头会有这个,我们需要用备份的sql + mysql—bin.000014开始数据回档恢复;

  ②mysqlbinlog  --no-defaults -v "/data/mysql/mysql-bin.000014",这个命令可以用来查看binlog日志,-v表示会转化为伪sql,从中截取了一段,begin开始,commit结束;我们使用mysqlbinlog搭配需要的时间进行数据恢复,大于,小于日志中记录的时间,也没有事,它会自动识别的

   ③数据恢复,备份的冷备sql,登录进入mysql服务器,source /冷备文件,就可以,binlog数据恢复:使用命令如下:

mysqlbinlog --no-defaults  --start-datetime="2023-07-19 08:18:50"   --stop-datetime="2023-07-19  14:20:45"    /data/mysql/mysql-bin.000023  | /usr/local/mysql/bin/mysql -uroot -pzzyy55555,前面参数就是开始时间(就是我们sql备份文件创建的时间),后面数据就是结束时间(我们需要回档到的目标时间),这里写全路径名是因为需要书写脚本自动执行;最后书写脚本,在java代码中执行脚本,传入参数是新建目的;需要传递两个备份日志的原因,是因为我们要筛选出,两个备份日志中间的binlog,才能更好的筛选哪些日志记录了我们需要 回档到目标时间那天的数据,(ps,就算不筛选也行,因为只要需要回档的时间,所有的日志执行也行);

./bach.sh   temp.sql   temp2.sql  "2023.07.23 15:18:00"

#!/bin/bash

#mysqldump -uroot -pzzyy55555 -B -F -R -x --source-data test > $(date +%F%T)back.sql;

#$1                 冷备日志需要传入
#$2                 冷备日志后一天的日志(传入为no 表示没有)
#$3                 回档目标时间

 

a=$(cat $1 |grep 'CHANGE MASTER TO MASTER_LOG_FILE')
echo $a
a=$(echo ${a#*\'});   
echo $a
a=$(echo ${a%\'*})
echo $a #回滚目标log日志



#冷备日志恢复
/usr/local/mysql/bin/mysql -uroot -pzzyy55555 -e "source /root/$1";
target="$3"

 #判断是今天回滚,还是今天之前回滚
if [ "$2" == no  ]; then
     echo "使用master进行备份"
     targetTime=`date "+%F %T" -r $1` #获取备份文件的创建日期
          echo "文件创建时间:$targetTime"
     rm -rf mysql-binlog.txt
      find  /data/mysql/* -newermt "$targetTime" -printf '%f\n' | grep mysql-bin |grep -v mysql-bin.index > mysql-binlog.txt;
     /usr/local/mysql/bin/mysql -uroot -pzzyy55555 -e "flush logs";
     cat mysql-binlog.txt | while read line;
     do  
        echo ${line}
        echo $targetTime
        echo $target 
       /usr/local/mysql/bin/mysqlbinlog --no-defaults  --start-datetime="$targetTime"   --stop-datetime="$target"                 /data/mysql/${line}  | /usr/local/mysql/bin/mysql -uroot -pzzyy55555
     done
else
      b=$(cat $2 |grep 'CHANGE MASTER TO MASTER_LOG_FILE')
      echo $b
      b=$(echo ${b#*\'});  
      echo $b
      b=$(echo ${b%\'*})
      echo $b #下一次的log日志

    echo "查询两个日志文件的备份"
    targetTime=`date "+%F %T" -r $1` #获取备份文件的创建日期
        echo "开始时间,文件创建时间 $targetTime "
    targetEndTime=`date "+%F %T" -r $2`
    targetEndTime=`date -d "$targetTime 10 minute" '+%Y-%m-%d %H:%M:%S' `
    echo "结束时间,第二个文件创建时间:$targetEndTime" 
    rm -rf mysql-binlog.txt 
    find  /data/mysql/* -newermt "$targetTime" ! -newermt "$targetEndTime" -printf '%f\n' | grep mysql-bin |grep -v mysql-bin.index > mysql-binlog.txt; 
 cat mysql-binlog.txt | while read line;
     do  
        echo ${line}
        echo $targetTime
        echo $target 
        /usr/local/mysql/bin/mysqlbinlog --no-defaults  --start-datetime="$targetTime"   --stop-datetime="$target"                 /data/mysql/${line}  | /usr/local/mysql/bin/mysql -uroot -pzzyy55555
     done
fi