MySQL備份之Xtrabackup

xtrabackup是percona公司專門針對mysql 數據庫開發的一款開源免費的物理備份(熱備)工具,能夠對innodb和xtradb等事務引擎數據庫實現非阻塞(即不鎖表)方式的備份,也能夠針對myisam等非事務引擎鎖表方式備份,是商業備份工具InnoDB Hotbackup的一個很好的替代品。mysql

一、介紹

1.一、主要特色

  • 物理備份工具,拷貝數據文件
  • 備份和恢復數據的速度很是快,安全可靠
  • 在備份期間執行的事務不會間斷,備份innodb數據不影響業務
  • 備份期間不增長太多數據庫的性能壓力
  • 支持對備份的數據自動校驗
  • 運行全量,增量,壓縮備份及流備份
  • 支持在線遷移表以及快速建立新的從庫
  • 運行幾乎全部版本的mysqlmaridb

1.二、相關詞彙

文件擴展名sql

文件擴展名 文件做用說明
.idb文件 以獨立表空間存儲的InnoDB引擎類型的數據文件擴展名
.ibdata文件 以共享表空間存儲的InnoDB引擎類型的數據文件擴展名
.frm文件 存放於表相關的元數據(meta)信息及表結構的定義信息
.MYD文件 存放MyISAM引擎表的數據文件擴展名
.MYI文件 存放MyISAM引擎表的索引信息文件擴展名

名詞數據庫

  • redo日誌
    redo日誌,也稱事務日誌,是innodb引擎的重要組成部分,做用是記錄innodb引擎中每個數據發生的變化信息。主要用於保證innodb數據的完整性,以及丟數據後的恢復,同時能夠有效提高數據庫的io等性能。redo日誌對應的配置參數爲innodb_log_file_sizeinnodb_log_files_in_groupcentos

  • Undo日誌
    Undo是記錄事務的逆向邏輯操做或者向物理操做對應的數據變化的內容,undo日誌默認存放在共享表空間裏面的ibdata*文件,和redo日誌功能不一樣undo日誌主要用於回滾數據庫崩潰前未完整提交的事務數據,確保數據恢復先後一致。數組

  • LSN
    LSN,全拼log sequence number,中文是日誌序列號,是一個64位的整型數字,LSN的做用是記錄redo日誌時,使用LSN惟一標識一條變化的數據。安全

  • checkpoint
    用來標識數據庫崩潰後,應恢復的redo log的起始點bash

1.三、XtraBackup備份原理

  1. checkpoint,記錄LSN號碼
  2. information schema.xxx備份
  3. 拷貝innoDB文件,過程當中發生的新變化redo也會被保存,保存至備份路徑
  4. Binlog只讀,FTWRL(global read lock)
  5. 拷貝Non InnoDB,拷貝完成解鎖
  6. 生成備份相關的信息文件:binlogLSN
  7. 刷新Last LSN
  8. 完成備份

備份時經歷的階段:服務器

  • InnoDB表:app

    • 熱備份:業務正常發生的時候,影響較小的備份方式
    • checkpoint:將已提交的數據頁刷新到磁盤,記錄一個LSN號碼
    • 拷貝InnoDB表相關的文件(ibdata1frmibd...)
    • 備份期間產生的新的數據變化redo也會備份走
  • 非InnoDB表:socket

    • 溫備份:鎖表備份
    • 觸發FTWRL全局鎖表
    • 拷貝非InnoDB表的數據
    • 解鎖

再次統計LSN號碼,寫入到專用文件xtrabackup checkpoint
記錄二進制日誌位置
全部備份文件統一存放在一個目錄下,備份完成

1.四、XtraBackup恢復步驟

  1. 作恢復前準備
  2. 作數據合併,增量和全備份的數據合併
  3. 全備數據,先把全備的redo lo文件內容和全備數據合併,而且read only不進行回滾
  4. 把第一次增量的redo log變化加載到第一次增量數據再與全量數據作合併
  5. 把第二次增量的redo log變化加載到第二次增量數據備份,在與全量和第一次增量的合併再進行合併, 最後把髒數據進行提交或回滾
  6. 恢復binlog的文件內容

二、安裝

2.一、安裝依賴包

# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
# yum -y install perl perl-devel libaio libaio-devel perl-Time-HiRes perl-DBD-MySQL libev

2.二、下載軟件並安裝

這裏使用的是清華源,官方地址下載較慢。
官方最新的是8.0版本,此版本只適用於mysql8.0版本的數據庫,因此這裏下載支持mysql5.6的版本

# wget -c https://mirrors.tuna.tsinghua.edu.cn/percona/centos/7/os/x86_64/percona-xtrabackup-24-2.4.18-1.el7.x86_64.rpm
# yum localinstall -y percona-xtrabackup-24-2.4.18-1.el7.x86_64.rpm

三、全量備份和恢復

3.一、前提

  • 數據庫處於運行狀態
  • xtrabackup能鏈接上數據庫:在mysql配置文件client下指定socket位置標籤或者在使用時指定
[client]
socket=/tmp/mysql.sock
  • 讀取配置文件mysqld下的datadir參數
[mysqld]
datadir=/usr/local/mysql/data
  • 開啓了binlog
log-bin = /data/mysql/mysql-bin
binlog_format="ROW"
expire_logs_days=3
  • xtrabackup是服務器端工具,不能遠程備份

3.二、全備

# innobackupex --user=root --password=123456 /backup/xbk/

在作全備時爲了控制生成的目錄名稱,能夠添加參數--no-timestamp並保留日期

# innobackupex --user=root --password=123456 --no-timestamp /backup/xbk/full_`date +%F`

3.三、備份結果

在備份目錄下查看備份的文件,除了mysql自身的數據文件外,還有這樣幾個文件

# pwd
/backup/xbk/2020-03-25_10-26-16
# ll
...
-rw-r-----. 1 root root       27 Mar 25 10:53 xtrabackup_binlog_info
-rw-r-----. 1 root root      147 Mar 25 10:53 xtrabackup_checkpoints
-rw-r-----. 1 root root      480 Mar 25 10:53 xtrabackup_info
-rw-r-----. 1 root root 31987200 Mar 25 10:53 xtrabackup_logfile
  • xtrabackup_binlog_info
    備份時刻的binlog位置
    記錄的是備份時刻,binlog的文件名字和當時的結束的position,能夠用來做爲截取binlog時的起點
# cat xtrabackup_binlog_info 
mysql-bin.000001        192790323
  • xtrabackup_checkpoints
    • 備份時刻,當即將已經commit過的,內存中的數據頁刷新到磁盤CKPT開始備份數據,數據文件的LSN會停留在to_lsn位置
    • 備份時刻有可能會有其餘的數據寫入,已備走的數據文件就不會再發生變化了
    • 在備份過程當中,備份軟件會一直監控着redoundo,若是一旦有變化會將日誌也一併備走,並記錄LSNlast_lsn,從to_lsn——>last_lsn就是,備份過程當中產生的數據變化
# cat xtrabackup_checkpoints 
backup_type = full-backuped
from_lsn = 0  					 # 上次所到達的LSN號(對於全備就是從0開始,對於增量有別的顯示方法)
to_lsn = 14194921406			# 備份開始時間(ckpt)點數據頁的LSN
last_lsn = 14200504300			# 備份結束後,redo日誌最終的LSN
compact = 0
recover_binlog_info = 0
flushed_lsn = 14177446392
  • xtrabackup_info
    備份的全局信息
# cat xtrabackup_info 
uuid = c04f3d33-6e43-11ea-9224-005056ac7d7c
name = 
tool_name = innobackupex
tool_command = --user=root --password=... /backup/xbk/
tool_version = 2.4.18
ibbackup_version = 2.4.18
server_version = 5.6.46-log
start_time = 2020-03-25 10:26:16
end_time = 2020-03-25 10:53:05
lock_time = 0
binlog_pos = filename 'mysql-bin.000001', position '192790323'
innodb_from_lsn = 0
innodb_to_lsn = 14194921406
partial = N
incremental = N
format = file
compact = N
compressed = N
encrypted = N
  • xtrabackup_logfile
    備份過程當中的redo,關聯在備份期間對InnoDB表產生的新變化

3.四、全備份的恢復

恢復流程:

  • xbk備份執行的瞬間,當即觸發ckpt,已提交的數據髒頁,從內存刷寫到磁盤,並記錄此時的LSN
  • 備份時,拷貝磁盤數據頁,而且記錄備份過程當中產生的redoundo一塊兒拷貝走,也就是checkpoint LSN以後的日誌
  • 在恢復以前,模擬Innodb「自動故障恢復」的過程,將redo(前滾)與undo(回滾)進行應用
  • 恢復過程是cp備份到原來數據目錄下

模擬數據庫宕機,刪除數據

# pkill mysqld
# rm -rf datadir=/usr/local/mysql/data/*

prepare預處理備份文件,將redo進行重作,已提交的寫到數據文件,未提交的使用undo回滾掉。模擬了CSR的過程

# innobackupex --apply-log  /backup/xbk/2020-03-25_10-26-16

數據恢復並啓動數據庫

# cp -a /backup/xbk/2020-03-25_10-26-16/* /usr/local/mysql/data/
# chown -R mysql.mysql /usr/local/mysql/data/
# /etc/init.d/mysqld start

四、增量備份和恢復

4.一、前提

增量必須依賴於全備
每次增量都是參照上次備份的LSN號碼(xtrabackup checkpoints),在此基礎上變化的數據頁進行備份
會將備份過程當中產生新的變化的redo一併備份走
恢復時增量備份沒法單獨恢復,必須基於全備進行恢復。必須將全部的增量備份,按順序所有合併到全備中

4.二、增量備份

  • 全量備份
# innobackupex --user=root --password --no-timestamp /backup/full >&/tmp/xbk_full.log
  • 第一次模擬新數據變化
db01 [(none)]>create database cs charset utf8;
db01 [(none)]>use cs
db01 [cs]>create table t1 (id int);
db01 [cs]>insert into t1 values(1),(2),(3);
db01 [cs]>commit;
  • 第一次增量備份
# innobackupex --user=root --password=123 --no-timestamp --incremental --incremental-basedir=/backup/full  /backup/inc1 &>/tmp/inc1.log

參數:
--incremental 增量備份,後面跟要增量備份的路徑
--incremental-basedir=DIRECTORY 基目錄,增量備份使用,上一次(全備)增量備份所在目錄

  • 第二次模擬新數據變化
db01 [cs]>create table t2 (id int);
db01 [cs]>insert into t2 values(1),(2),(3);
db01 [cs]>commit;
  • 第二次增量備份
# innobackupex --user=root --password=123 --no-timestamp --incremental --incremental-basedir=/backup/inc1  /backup/inc2  &>/tmp/inc2.log
  • 第三次模擬新數據變化
db01 [cs]>create table t3 (id int);
db01 [cs]>insert into t3 values(1),(2),(3);
db01 [cs]>commit;
db01 [cs]>drop database cs;

4.三、備份恢復

恢復流程:

  • 掛出維護頁,中止當天的自動備份腳本
  • 檢查備份:full+inc1+inc2+最新的完整二進制日誌
  • 進行備份整理(細節),截取關鍵的二進制日誌(從備份——誤刪除以前)
  • 測試庫進行備份恢復及日誌恢復
  • 應用進行測試無誤,開啓業務

模擬數據庫宕機,刪除數據

# pkill mysqld
# rm -rf datadir=/usr/local/mysql/data/*

確認備份完整性,對比每一個備份集中的checkpoints文件

全備份的checkpoints文件內容以下,能夠發現to_lsnlast_lsn中間相差9。這個數字差在5.7版本前爲0,二者相等,在5.7版本後開啓GTID後有了這個差值,做爲內部使用。因此若是是知足這個條件,那麼能夠認爲備份期間並無新的數據修改。一樣的,在增量備份的備份集下的文件也是如此,且增量備份from_lsn號與相鄰的上一個備份的last_lsn減去9是一致的。

# cat full/xtrabackup_checkpoints
backup_type = full-backuped
from_lsn = 0
to_lsn = 337979814
last_lsn = 337979823
compact = 0
recover_binlog_info = 0
# cat inc1/xtrabackup_checkpoints
backup_type = incremental
from_lsn = 337979814
to_lsn = 337985758
last_lsn = 337985767
compact = 0
recover_binlog_info = 0
# cat inc2/xtrabackup_checkpoints
backup_type = incremental
from_lsn = 337985758
to_lsn = 337991702
last_lsn = 337991711
compact = 0
recover_binlog_info = 0

合併整理全部(apply-log)備份(full+inc1+inc2)到全備:

  • 基礎全備整理

--redo-only參數表示只應用redo,不進行undo,防止LSN號發生變化,除最後一次的備份合併外都須要加此參數

# innobackupex --apply-log --redo-only /data/backup/full
  • 合併增量到全備中
    合併完能夠發現每一個備份集中的check_points文件的last_lsn相同,說明合併成功
# 合併inc1到full中
# innobackupex --apply-log --redo-only --incremental-dir=/data/backup/inc1 /data/backup/full
# 合併inc2到full中(最後一次增量)
# innobackupex --apply-log  --incremental-dir=/data/backup/inc2 /data/backup/full
  • 最後一次整理全備
# innobackupex --apply-log  /data/backup/full
  • 數據恢復並啓動數據庫
# cp -a /backup/full/* /usr/local/mysql/data/
# chown -R mysql.mysql /usr/local/mysql/data/
# /etc/init.d/mysqld start
  • 截取刪除時刻 到drop以前的 binlog

查看最後一次增量備份中的文件內容

# cat /data/backup/inc2/xtrabackup_binlog_info
mysql-bin.000020 1629 9b8e7056-4d4c-11ea-a231-000c298e182d:1-19. df04d325-5946-11ea-000c298e182d:1-7
# mysqlbinlog --skip-gtids --start-position=1629 /data/binlog/mysql-bin.000020 >/data/backup/binlog.sql
或
# mysqlbinlog --skip-gtids --include-gtids='9b8e7056-4d4c-11ea-a231-000c298e182d:1-19' /data/binlog/mysql-bin.000020 >/data/backup/binlog.sql

登陸mysql,恢復最後的sql

Master [(none)]>set sql_log_bin=0;
Master [(none)]>source /data/backup/binlog.sql
Master [(none)]>set sql_log_bin=1;

恢復完成。

五、生產案例

5.一、生產場景

現有一個生產數據庫,總數據量3TB,共10個業務,10個庫500張表。週三上午10點,誤DROPtaobao.1業務核心表20GB,致使taobao庫業務沒法正常運行。
採用的備份策略是:週日full全備,週一到週五inc增量備份,binlog完整
針對此種場景,怎麼快速恢復業務,還不影響其餘業務?

5.二、實現思路

遷移表空間

create table t1;
alter table taobao.t1 discard tablespace;
alter table taobao.t1 import tablespace;

一、要想恢復單表,須要表結構和數據
首先合併備份到最新的備份
如何獲取表結構?藉助工具mysqlfrm

yum install -y mysql-utilities

二、獲取建表語句

# mysqlfrm —diagnostic t2.frm
create table `t2` (
`id` int(11) default null
) engine=InnoDB;

三、進入數據庫中建立表

create table `t2` (
`id` int(11) default null
) engine=InnoDB;

四、丟棄新建的表空間

alter table t2 discard tablespace;

五、將表中的數據cp回數據庫數據目錄

cp t2.ibd /data/23306/xbk/
chown mysql:mysql /data/3306/xbk/t2.ibd

六、導入表空間

alter table t2 import tablespace;

七、切割二進制日誌到刪庫前生成sql並導入

六、備份腳本

6.一、備份用戶建立

建立一個專用於備份的受權用戶

create user 'back'@'localhost' identified by '123456';
grant reload,lock tables,replication client,create tablespace,process,super on *.* to 'back'@'localhost' ;
grant create,insert,select on percona_schema.* to 'back'@'localhost';

6.二、全量備份

mybak-all.sh

#!/bin/bash
#全量備份,只備份一次
#指定備份目錄
backup_dir="/bak/mysql-xback"
#檢查
[[ -d ${backup_dir} ]] || mkdir -p ${backup_dir}
if [[ -d ${backup_dir}/all-backup ]];then
    echo "全備份已存在"
    exit 1
fi
#命令,須要設置
innobackupex --defaults-file=/etc/my.cnf --user=back --password='123456' --no-timestamp ${backup_dir}/all-backup &> /tmp/mysql-backup.log
tail -n 1  /tmp/mysql-backup.log | grep 'completed OK!'
if [[ $? -eq 0 ]];then
    echo "all-backup" > /tmp/mysql-backup.txt
else
    echo "備份失敗"
    exit 1
fi

6.三、增量備份

mybak-section.sh

#!/bin/bash
#增量備份
#備份目錄
backup_dir="/bak/mysql-xback"
#新舊備份
old_dir=`cat /tmp/mysql-backup.txt`
new_dir=`date +%F-%H-%M-%S`
#檢查
if [[ ! -d ${backup_dir}/all-backup ]];then
    echo "還未全量備份"
    exit 1
fi
#命令
/usr/bin/innobackupex --user=back --password='123456' --no-timestamp --incremental --incremental-basedir=${backup_dir}/${old_dir} ${backup_dir}/${new_dir} &> /tmp/mysql-backup.log
tail -n 1  /tmp/mysql-backup.log | grep 'completed OK!'
if [[ $? -eq 0 ]];then
    echo "${new_dir}" > /tmp/mysql-backup.txt
else
    echo "備份失敗"
    exit 1
fi

6.四、binlog備份

單點,備份binlog,要指定備份目錄位置和其它變量

#!/bin/bash
#
# 注意:執行腳本前修改腳本中的變量
# 功能:cp方式增量備份
#
# 適用:centos6+
# 語言:中文
#
#使用:./xx.sh -uroot -p'123456',將第一次增量備份後的binlog文件名寫到/tmp/binlog-section中,若都沒有,自動填寫mysql-bin.000001
#過程:增量先刷新binlog日誌,再查詢/tmp/binlog-section中記錄的上一次備份中最新的binlog日誌的值
#      cp中間的binlog日誌,並進行壓縮。再將備份中最新的binlog日誌寫入。
#恢復:先進行全量恢復,再根據全量備份附帶的time-binlog.txt中的記錄逐個恢復。當前最新的Binlog日誌要去掉有問題的語句,例如drop等。
#[變量]
#mysql這個命令所在絕對路徑
my_sql="/usr/local/mysql/bin/mysql"
#mysqldump命令所在絕對路徑
bak_sql="/usr/local/mysql/bin/mysqldump"
#binlog日誌所在目錄
binlog_dir=/usr/local/mysql/data
#mysql-bin.index文件所在位置
binlog_index=${binlog_dir}/mysql-bin.index
#備份到哪一個目錄
bak_dir=/bak/mysql-binback
#這個腳本的日誌輸出到哪一個文件
log_dir=/tmp/mybak-binlog.log
#保存的天數,4周就是28天
save_day=10
#[自動變量]
#當前年
date_nian=`date +%Y-`
begin_time=`date +%F-%H-%M-%S`
#全部天數的數組
save_day_zu=($(for i in `seq 1 ${save_day}`;do date -d -${i}days "+%F";done))
#開始
/usr/bin/echo >> ${log_dir}
/usr/bin/echo "time:$(date +%F-%H-%M-%S) info:開始增量備份" >> ${log_dir}
#檢查
${my_sql} $* -e "show databases;" &> /tmp/info_error.txt
if [[ $? -ne 0 ]];then
    /usr/bin/echo "time:$(date +%F-%H-%M-%S) info:登錄命令錯誤" >> ${log_dir}
    /usr/bin/cat /tmp/info_error.txt #若是錯誤則顯示錯誤信息
    exit 1
fi
#移動到目錄
cd ${bak_dir}
bak_time=`date +%F-%H-%M`
bak_timetwo=`date +%F`
#刷新
${my_sql} $* -e "flush logs"
if [[ $? -ne 0 ]];then
    /usr/bin/echo "time:$(date +%F-%H-%M-%S) error:刷新binlog失敗" >> ${log_dir}
    exit 1
fi
#獲取開頭和結尾binlog名字
last_bin=`cat /tmp/binlog-section`
next_bin=`tail -n 1 ${binlog_dir}/mysql-bin.index`
echo ${last_bin} |grep 'mysql-bin' &> /dev/null
if [[ $? -ne 0 ]];then
    echo "mysql-bin.000001" > /tmp/binlog-section #不存在則默認第一個
    last_bin=`cat /tmp/binlog-section`
fi
#截取須要備份的binlog行數
a=`/usr/bin/sort ${binlog_dir}/mysql-bin.index | uniq | grep -n ${last_bin} | awk -F':' '{print $1}'`
b=`/usr/bin/sort ${binlog_dir}/mysql-bin.index | uniq | grep -n ${next_bin} | awk -F':' '{print $1}'`
let b--
#輸出最新節點
/usr/bin/echo "${next_bin}" > /tmp/binlog-section
#建立文件
rm -rf mybak-section-${bak_time}
/usr/bin/mkdir mybak-section-${bak_time}
for i in `sed -n "${a},${b}p" ${binlog_dir}/mysql-bin.index  | awk -F'./' '{print $2}'`
do
    if [[ ! -f ${binlog_dir}/${i} ]];then
        /usr/bin/echo "time:$(date +%F-%H-%M-%S) error:binlog文件${i} 不存在" >> ${log_dir}
        exit 1
    fi
    cp -rf ${binlog_dir}/${i} mybak-section-${bak_time}/
    if [[ ! -f mybak-section-${bak_time}/${i} ]];then
        /usr/bin/echo "time:$(date +%F-%H-%M-%S) error:binlog文件${i} 備份失敗" >> ${log_dir}
        exit 1
    fi
done
#壓縮
if [[ -f mybak-section-${bak_time}.tar.gz ]];then
    /usr/bin/echo "time:$(date +%F-%H-%M-%S) info:壓縮包mybak-section-${bak_time}.tar.gz 已存在" >> ${log_dir}
    /usr/bin/rm -irf mybak-section-${bak_time}.tar.gz
fi
/usr/bin/tar -cf mybak-section-${bak_time}.tar.gz mybak-section-${bak_time}
if [[ $? -ne 0 ]];then
    /usr/bin/echo "time:$(date +%F-%H-%M-%S) error:壓縮失敗" >> ${log_dir}
    exit 1
fi
#刪除binlog文件夾
/usr/bin/rm -irf mybak-section-${bak_time}
if [[ $? -ne 0 ]];then
    /usr/bin/echo "time:$(date +%F-%H-%M-%S) info:刪除sql文件失敗" >> ${log_dir}
    exit 1
fi
#整理壓縮的日誌文件
for i in `ls | grep "^mybak-section.*tar.gz$"`
   do
    echo $i | grep ${date_nian} &> /dev/null
        if [[ $? -eq 0 ]];then
            a=`echo ${i%%.tar.gz}`
            b=`echo ${a:(-16)}` #當前日誌年月日
            c=`echo ${b%-*}`
            d=`echo ${c%-*}`
            #看是否在數組中,不在其中,而且不是當前時間,則刪除。
            echo ${save_day_zu[*]} |grep -w $d &> /dev/null
            if [[ $? -ne 0 ]];then
                [[ "$d" != "$bak_timetwo" ]] && rm -rf $i
            fi
        else
            #不是當月的,其餘類型壓縮包,跳過
            continue
        fi
done
#結束
last_time=`date +%F-%H-%M-%S`
/usr/bin/echo "begin_time:${begin_time}   last_time:${last_time}" >> ${log_dir}
/usr/bin/echo "time:$(date +%F-%H-%M-%S) info:增量備份完成" >> ${log_dir}
/usr/bin/echo >> ${log_dir}

主從,備份relay-bin,要指定備份目錄位置和其它變量

#!/bin/bash
#
# 注意:執行腳本前修改腳本中的變量
# 功能:cp方式增量備份
#
# 適用:centos6+
# 語言:中文
#
#使用:./xx.sh -uroot -p'123456'
#[變量]
#mysql這個命令所在絕對路徑
my_sql="/usr/local/mysql/bin/mysql"
#mysqldump命令所在絕對路徑
bak_sql="/usr/local/mysql/bin/mysqldump"
#binlog日誌所在目錄
binlog_dir=/usr/local/mysql/data
#mysql-bin.index文件所在位置
binlog_index=${binlog_dir}/mysql-bin.index
#備份到哪一個目錄
bak_dir=/bak/mysql-binback
#這個腳本的日誌輸出到哪一個文件
log_dir=/tmp/mybak-binlog.log
#保存的天數,4周就是28天
save_day=10
#[自動變量]
#當前年
date_nian=`date +%Y-`
begin_time=`date +%F-%H-%M-%S`
#全部天數的數組
save_day_zu=($(for i in `seq 1 ${save_day}`;do date -d -${i}days "+%F";done))
#開始
/usr/bin/echo >> ${log_dir}
/usr/bin/echo "time:$(date +%F-%H-%M-%S) info:開始增量備份" >> ${log_dir}
#檢查
${my_sql} $* -e "show databases;" &> /tmp/info_error.txt
if [[ $? -ne 0 ]];then
    /usr/bin/echo "time:$(date +%F-%H-%M-%S) info:登錄命令錯誤" >> ${log_dir}
    /usr/bin/cat /tmp/info_error.txt #若是錯誤則顯示錯誤信息
    exit 1
fi
#移動到目錄
cd ${bak_dir}
bak_time=`date +%F-%H-%M`
bak_timetwo=`date +%F`
#建立文件
rm -rf mybak-section-${bak_time}
/usr/bin/mkdir mybak-section-${bak_time}
for i in `ls ${binlog_dir}| grep relay-bin`
do
    cp -rf ${binlog_dir}/${i} mybak-section-${bak_time}/
    if [[ ! -f mybak-section-${bak_time}/${i} ]];then
        /usr/bin/echo "time:$(date +%F-%H-%M-%S) error:binlog文件${i} 備份失敗" >> ${log_dir}
        exit 1
    fi
done
#壓縮
if [[ -f mybak-section-${bak_time}.tar.gz ]];then
    /usr/bin/echo "time:$(date +%F-%H-%M-%S) info:壓縮包mybak-section-${bak_time}.tar.gz 已存在" >> ${log_dir}
    /usr/bin/rm -irf mybak-section-${bak_time}.tar.gz
fi
/usr/bin/tar -cf mybak-section-${bak_time}.tar.gz mybak-section-${bak_time}
if [[ $? -ne 0 ]];then
    /usr/bin/echo "time:$(date +%F-%H-%M-%S) error:壓縮失敗" >> ${log_dir}
    exit 1
fi
#刪除binlog文件夾
/usr/bin/rm -irf mybak-section-${bak_time}
if [[ $? -ne 0 ]];then
    /usr/bin/echo "time:$(date +%F-%H-%M-%S) info:刪除sql文件失敗" >> ${log_dir}
    exit 1
fi
#整理壓縮的日誌文件
for i in `ls | grep "^mybak-section.*tar.gz$"`
   do
    echo $i | grep ${date_nian} &> /dev/null
        if [[ $? -eq 0 ]];then
            a=`echo ${i%%.tar.gz}`
            b=`echo ${a:(-16)}` #當前日誌年月日
            c=`echo ${b%-*}`
            d=`echo ${c%-*}`
            #看是否在數組中,不在其中,而且不是當前時間,則刪除。
            echo ${save_day_zu[*]} |grep -w $d &> /dev/null
            if [[ $? -ne 0 ]];then
                [[ "$d" != "$bak_timetwo" ]] && rm -rf $i
            fi
        else
            #不是當月的,其餘類型壓縮包,跳過
            continue
        fi
done
#結束
last_time=`date +%F-%H-%M-%S`
/usr/bin/echo "begin_time:${begin_time}   last_time:${last_time}" >> ${log_dir}
/usr/bin/echo "time:$(date +%F-%H-%M-%S) info:增量備份完成" >> ${log_dir}
/usr/bin/echo >> ${log_dir}
相關文章
相關標籤/搜索