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
資料不影響業務 - 備份期間不增加太多資料庫的效能壓力
- 支援對備份的資料自動校驗
- 執行全量,增量,壓縮備份及流備份
- 支援線上遷移表以及快速建立新的從庫
- 執行幾乎所有版本的
mysql
和maridb
1.2、相關詞彙
副檔名
副檔名 | 檔案作用說明 |
---|---|
.idb檔案 | 以獨立表空間儲存的InnoDB引擎型別的資料副檔名 |
.ibdata檔案 | 以共享表空間儲存的InnoDB引擎型別的資料副檔名 |
.frm檔案 | 存放於表相關的元資料(meta)資訊及表結構的定義資訊 |
.MYD檔案 | 存放MyISAM引擎表的資料副檔名 |
.MYI檔案 | 存放MyISAM引擎表的索引資訊副檔名 |
名詞
-
redo日誌
redo
日誌,也稱事務日誌,是innodb
innodb
引擎中每一個數據發生的變化資訊。主要用於保證innodb
資料的完整性,以及丟資料後的恢復,同時可以有效提升資料庫的io
等效能。redo
日誌對應的配置引數為innodb_log_file_size
和innodb_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備份原理
-
checkpoint
,記錄LSN
號碼 -
information schema.xxx
備份 - 拷貝
innoDB
檔案,過程中發生的新變化redo
也會被儲存,儲存至備份路徑 -
Binlog
只讀,FTWRL
(global read lock) - 拷貝
Non InnoDB
,拷貝完成解鎖 - 生成備份相關的資訊檔案:
binlog
、LSN
- 重新整理
Last LSN
- 完成備份
備份時經歷的階段:
-
InnoDB表:
- 熱備份:業務正常發生的時候,影響較小的備份方式
-
checkpoint
:將已提交的資料頁重新整理到磁碟,記錄一個LSN
號碼 - 拷貝
InnoDB
表相關的檔案(ibdata1
、frm
、ibd
...) - 備份期間產生的新的資料變化
redo
也會備份走
-
非InnoDB表:
- 溫備份:鎖表備份
- 觸發
FTWRL
全域性鎖表 - 拷貝非
InnoDB
表的資料 - 解鎖
再次統計LSN
號碼,寫入到專用檔案xtrabackup checkpoint
記錄二進位制日誌位置
所有備份檔案統一存放在一個目錄下,備份完成
1.4、XtraBackup恢復步驟
- 做恢復前準備
- 做資料合併,增量和全備份的資料合併
- 全備資料,先把全備的
redo lo
檔案內容和全備資料合併,並且read only
不進行回滾 - 把第一次增量的
redo log
變化載入到第一次增量資料再與全量資料做合併 - 把第二次增量的
redo log
變化載入到第二次增量資料備份,在與全量和第一次增量的合併再進行合併, 最後把髒資料進行提交或回滾 - 恢復
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
位置 - 備份時刻有可能會有其他的資料寫入,已備走的資料檔案就不會再發生變化了
- 在備份過程中,備份軟體會一直監控著
redo
的undo
,如果一旦有變化會將日誌也一併備走,並記錄LSN
到last_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
號 - 備份時,拷貝磁碟資料頁,並且記錄備份過程中產生的
redo
和undo
一起拷貝走,也就是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_lsn
和last_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
點,誤DROP
了taobao.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}