1. 程式人生 > 其它 >MySQL備份之Xtrabackup☃️⛄

MySQL備份之Xtrabackup☃️⛄

MySQL備份之Xtrabackup☃️❄️

原文連結:https://www.ssgeek.com/post/mysql-bei-fen-zhi-xtrabackup/

 

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

1、介紹

1.1、主要特點

  • 物理備份工具,拷貝資料檔案
  • 備份和恢復資料的速度非常快,安全可靠
  • 在備份期間執行的事務不會間斷,備份innodb資料不影響業務
  • 備份期間不增加太多資料庫的效能壓力
  • 支援對備份的資料自動校驗
  • 執行全量,增量,壓縮備份及流備份
  • 支援線上遷移表以及快速建立新的從庫
  • 執行幾乎所有版本的mysqlmaridb

1.2、相關詞彙

副檔名

副檔名 檔案作用說明
.idb檔案 以獨立表空間儲存的InnoDB引擎型別的資料副檔名
.ibdata檔案 以共享表空間儲存的InnoDB引擎型別的資料副檔名
.frm檔案 存放於表相關的元資料(meta)資訊及表結構的定義資訊
.MYD檔案 存放MyISAM引擎表的資料副檔名
.MYI檔案 存放MyISAM引擎表的索引資訊副檔名

名詞

  • redo日誌
    redo日誌,也稱事務日誌,是innodb

    引擎的重要組成部分,作用是記錄innodb引擎中每一個數據發生的變化資訊。主要用於保證innodb資料的完整性,以及丟資料後的恢復,同時可以有效提升資料庫的io等效能。redo日誌對應的配置引數為innodb_log_file_sizeinnodb_log_files_in_group

  • Undo日誌
    Undo是記錄事務的逆向邏輯操作或者向物理操作對應的資料變化的內容,undo日誌預設存放在共享表空間裡面的ibdata*檔案,和redo日誌功能不同undo日誌主要用於回滾資料庫崩潰前未完整提交的事務資料,確保資料恢復前後一致。

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

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

1.3、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表:

    • 熱備份:業務正常發生的時候,影響較小的備份方式
    • checkpoint:將已提交的資料頁重新整理到磁碟,記錄一個LSN號碼
    • 拷貝InnoDB表相關的檔案(ibdata1frmibd...)
    • 備份期間產生的新的資料變化redo也會備份走
  • 非InnoDB表:

    • 溫備份:鎖表備份
    • 觸發FTWRL全域性鎖表
    • 拷貝非InnoDB表的資料
    • 解鎖

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

1.4、XtraBackup恢復步驟

  1. 做恢復前準備
  2. 做資料合併,增量和全備份的資料合併
  3. 全備資料,先把全備的redo lo檔案內容和全備資料合併,並且read only不進行回滾
  4. 把第一次增量的redo log變化載入到第一次增量資料再與全量資料做合併
  5. 把第二次增量的redo log變化載入到第二次增量資料備份,在與全量和第一次增量的合併再進行合併, 最後把髒資料進行提交或回滾
  6. 恢復binlog的檔案內容

2、安裝

2.1、安裝依賴包

# 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.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、全量備份和恢復

3.1、前提

  • 資料庫處於執行狀態
  • 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.2、全備

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

在做全備時為了控制生成的目錄名稱,可以新增引數--no-timestamp並保留日期

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

3.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.4、全備份的恢復

恢復流程:

  • 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、增量備份和恢復

4.1、前提

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

4.2、增量備份

  • 全量備份
# 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.3、備份恢復

恢復流程:

  • 掛出維護頁,停止當天的自動備份指令碼
  • 檢查備份: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、生產案例

5.1、生產場景

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

5.2、實現思路

遷移表空間

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

1、要想恢復單表,需要表結構和資料
首先合併備份到最新的備份
如何獲取表結構?藉助工具mysqlfrm

yum install -y mysql-utilities

2、獲取建表語句

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

3、進入資料庫中建立表

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

4、丟棄新建的表空間

alter table t2 discard tablespace;

5、將表中的資料cp回資料庫資料目錄

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

6、匯入表空間

alter table t2 import tablespace;

7、切割二進位制日誌到刪庫前生成sql並匯入

6、備份指令碼

6.1、備份使用者建立

建立一個專用於備份的授權使用者

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.2、全量備份

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.3、增量備份

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.4、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}