mysql用sql语句怎么做个脚本备份_mysql备份脚本
一、介紹兩種日志
1、redo log是InnoDB存儲引擎層的日志,又稱重做日志文件,用于記錄事務操作的變化,記錄的是數據修改之后的值,不管事務是否提交都會記錄下來。在實例和介質失敗(media failure)時,redo log文件就能派上用場,如數據庫掉電,InnoDB存儲引擎會使用redo log恢復到掉電前的時刻,以此來保證數據的完整性。
在一條更新語句進行執行的時候,InnoDB引擎會把更新記錄寫到redo log日志中,然后更新內存,此時算是語句執行完了,然后在空閑的時候或者是按照設定的更新策略將redo log中的內容更新到磁盤中,這里涉及到WAL即Write Ahead logging技術,他的關鍵點是先寫日志,再寫磁盤。
有了redo log日志,那么在數據庫進行異常重啟的時候,可以根據redo log日志進行恢復,也就達到了crash-safe。
redo log日志的大小是固定的,即記錄滿了以后就從頭循環寫。
2、binlog是屬于MySQL Server層面的,又稱為歸檔日志,屬于邏輯日志,是以二進制的形式記錄的是這個語句的原始邏輯,依靠binlog是沒有crash-safe能力的
3、區別:
redo log是屬于innoDB層面,binlog屬于MySQL Server層面的,這樣在數據庫用別的存儲引擎時可以達到一致性的要求。
redo log是物理日志,記錄該數據頁更新的內容;binlog是邏輯日志,記錄的是這個更新語句的原始邏輯
redo log是循環寫,日志空間大小固定;binlog是追加寫,是指一份寫到一定大小的時候會更換下一個文件,不會覆蓋。
binlog可以作為恢復數據使用,主從復制搭建,redo log作為異常宕機或者介質故障后的數據恢復使用。
二、xtra+binlog增量備份腳本
1、特點
mysqldump優點:mysqldump的優點就是邏輯備份,把數據生成SQL形式保存,在單庫,單表數據遷移,備份恢復等場景方便,SQL形式的備份文件通用,也方便在不同數據庫之間移植。對于InnoDB表可以在線備份。
mysqldump缺點:mysqldump是單線程,數據量大的時候,備份時間長,甚至有可能在備份過程中非事務表長期鎖表對業務造成影響(SQL形式的備份恢復時間也比較長)。mysqldump備份時會查詢所有的數據,這可能會把內存中的熱點數據刷掉
innobackupex優點:物理備份可以繞過MySQL Server層,加上本身就是文件系統級別的備份,備份速度塊,恢復速度快,可以在線備份,支持并發備份,支持加密傳輸,支持備份限速
innobackupex缺點:要提取部分庫表數據比較麻煩,不能按照基于時間點來恢復數據,并且不能遠程備份,只能本地備份,增量備份的恢復也比較麻煩。如果使用innobackupex的全備+binlog增量備份就可以解決基于時間點恢復的問題。
2、備份策略
根據需求,使用innobackupex全備份+innobackupex增量備份+binlog方式進行備份。
在出現問題時使用innobackupex快速的恢復
3、環境準備
開啟binlog
編輯/etc/my.cnf文件添加在[mysqld]版塊下添加如下變量,添加后重啟服務。
#開啟,并且可以將mysql-bin改為其它的日志名
log-bin=mysql-bin
#添加id號,如果做主從,就不能一樣
server-id=1#超過200M將生產新的文件,最大和默認值是1GB
max_binlog_size=1G
#此參數表示binlog使用最大內存的數,默認1M。
max_binlog_cache_size=1M
#此參數表示binlog日志保留的時間,默認單位是天。
expire_logs_days=7
創建授權用戶
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';
安裝innobackupex
1.安裝依賴yum -y install perl perl-devel libaio libaio-devel perl-Time-HiRes perl-DBD-MySQL libev-devel2.下載安裝wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.12/binary/redhat/7/x86_64/percona-xtrabackup-24-2.4.12-1.el7.x86_64.rpm
yum -y install percona-xtrabackup-24-2.4.12-1.el7.x86_64.rpm
三.添加腳本
全量備份
創建備份目錄mkdir -p /root/binmkdir -p /bak/mysql-xback
編寫腳本,要指定備份命令的賬號和密碼
vim/root/bin/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 "全備份已存在"exit1
fi#命令,需要設置
innobackupex--defaults-file=/etc/my.cnf --user=back --password='123456' --no-timestamp ${backup_dir}/all-backup &> /tmp/mysql-backup.logtail -n 1 /tmp/mysql-backup.log | grep 'completed OK!'
if [[ $? -eq 0 ]];then
echo "all-backup" > /tmp/mysql-backup.txtelse
echo "備份失敗"exit1
fi
增量備份
編寫腳本,要指定備份目錄
vim/root/bin/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 "還未全量備份"exit1
fi#命令/usr/bin/innobackupex --user=back --password='123456' --no-timestamp --incremental --incremental-basedir=${backup_dir}/${old_dir} ${backup_dir}/${new_dir} &> /tmp/mysql-backup.logtail -n 1 /tmp/mysql-backup.log | grep 'completed OK!'
if [[ $? -eq 0 ]];then
echo "${new_dir}" > /tmp/mysql-backup.txtelse
echo "備份失敗"exit1
fi
binlog
創建備份目錄mkdir -p /bak/mysql-binback
用于單點,備份binlog,要指定備份目錄位置和其它變量
vim/root/bin/mybak-binlog.sh#!/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.txtif [[ $? -ne 0 ]];then
/usr/bin/echo "time:$(date +%F-%H-%M-%S) info:登陸命令錯誤" >>${log_dir}/usr/bin/cat /tmp/info_error.txt #如果錯誤則顯示錯誤信息
exit1
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}
exit1
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}
exit1
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}
exit1
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.gzfi
/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}
exit1
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}
exit1
fi#整理壓縮的日志文件for i in `ls | grep "^mybak-section.*tar.gz$"`do
echo $i | grep ${date_nian} &> /dev/null
if [[ $? -eq 0 ]];thena=`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 $ifi
else#不是當月的,其他類型壓縮包,跳過
continuefi
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,要指定備份目錄位置和其它變量
vim/root/bin/mybak-binlog.sh#!/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.txtif [[ $? -ne 0 ]];then
/usr/bin/echo "time:$(date +%F-%H-%M-%S) info:登陸命令錯誤" >>${log_dir}/usr/bin/cat /tmp/info_error.txt #如果錯誤則顯示錯誤信息
exit1
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}
exit1
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.gzfi
/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}
exit1
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}
exit1
fi#整理壓縮的日志文件for i in `ls | grep "^mybak-section.*tar.gz$"`do
echo $i | grep ${date_nian} &> /dev/null
if [[ $? -eq 0 ]];thena=`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 $ifi
else#不是當月的,其他類型壓縮包,跳過
continuefi
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}
重寫備份
創建備份目錄mkdir -p /bak/xback
編寫腳本,要指定備份目錄位置
vim/root/bin/mybak-rewrite.sh#!/bin/bash
#xbak備份腳本
#每周六執行一次
#10 4 * * 6 /bin/bash /root/bin/mybak-rewrite.sh#清理并備份
[[-d /bak/xback ]] || mkdir -p /bak/xback
cd/bak/xbackrm -rf *.tar.gz
[[-d bak/mysql-xback ]] || echo "bak-dir not found"cd/bak/mysql-xbacktar -cf XtraBackup.tar.gz *
mv XtraBackup.tar.gz /bak/xbackrm -rf /bak/mysql-xback/*#全備份一次
bash /root/bin/mybak-all.sh
備份周期
添加權限chmod +x /root/bin/*先進行一次innobackupex全量備份,后面的增量均在全量的基礎上備份。
bash /root/bin/mybak-all.sh
每天2點進行一次innobackupex增量備份+binlog日志備份
每周4點將之前的innobackupex備份打包,并啟動新的全量備份
crontab -e
30 2 * * * /bin/bash /root/bin/mybak-binlog.sh -uback -p'123456'
40 2 * * * /bin/bash /root/bin/mybak-section.sh
10 4 * * 6 /bin/bash /root/bin/mybak-rewrite.sh
四.容災測試
寫入測試數據
創建腳本,腳本將創建一個single庫,s1表,持續寫入數據。
vim/root/bin/mysql_test.sh#!/bin/bash
#混合測試數據庫腳本
#將創建一個single數據庫,其中創建一個s1表
#如果數據庫存在,將會寫入數據,可以在寫入部分sleep1來讓數據持續寫入
#使用方法 ./xx.sh -uroot -p'123456'#檢查
mysql $* -e "show databases;" &> /tmp/info_error.txtif [[ $? -ne 0 ]];then
echo "time:$(date +%F-%H-%M-%S) info:登陸命令錯誤"
cat /tmp/info_error.txt #如果錯誤則顯示錯誤信息echo
echo "./xx.sh -uroot -p'123456'"exit1
fi#檢查庫是否存在
mysql $* -e "use single;" &> /tmp/info_error.txtif [[ $? -eq 0 ]];thenmysql $* -e "use single;select * from s1 where id=1;"
if [[ $? -ne 0 ]];thenmysql $* -e "use single;drop table s1;"mysql $* -e "use single;create table s1(id int AUTO_INCREMENT PRIMARY KEY,name char(20),age int);"
fi
elsemysql $* -e "create database single;"mysql $* -e "use single;create table s1(id int AUTO_INCREMENT PRIMARY KEY,name char(20),age int);"
fi#name隨機數
random_name() {
local zu=(q we r t y u i o p a s d f g h j k l z x c v b n m)for i in `seq 1 5`dolocal a=`echo $[RANDOM%24]`echo -n ${zu[a]}done}
#age隨機數
random_age() {
local a=`echo $[RANDOM%99]`echo$a
}
#寫入部分for i in `seq 1 1000`dob=`random_name`
c=`random_age`sleep 2mysql $* -e "use single;insert into s1(name,age) values('${b}',${c});"
done執行腳本,持續寫入測試數據
bash/root/bin/mysql_test.sh -uroot -p'123456'
模擬備份
1.開啟另一個終端,檢查數據是否在寫入
mysql-uroot -p'123456' -e "use single;select count(*) from s1;"
2.進行全備份,返回ok正確
cd/root/bin
bash mybak-all.sh
3.模擬第一天晚上,因為在持續寫入數據,等一會再進行增量備份,并備份binlog
bash mybak-section.shbash mybak-binlog.sh -uback -p'123456'
4.等一會,模擬第二天晚上
bash mybak-section.shbash mybak-binlog.sh -uback -p'123456'
錯誤恢復
1.模擬出現問題了,停止寫入
ctl+c2.查看當前總數據,為129條
mysql-uroot -p'123456' -e "use single;select count(*) from s1;"
3.模擬誤刪除數據庫
mysql-uroot -p'123456' -e "drop database single;"
4.對最新的狀態備份binlog
bash mybak-binlog.sh -uback -p'123456'
5.關閉mysql
systemctl stop mysql6.刪除數據目錄,否則無法恢復rm -fr /usr/local/mysql/data/*7.對全備份進行封裝,返回ok正確
innobackupex --apply-log --redo-only /bak/mysql-xback/all-backup/
8.合并第一次模擬到全備份,最后一個參數是指定全備份
innobackupex --apply-log --redo-only --incremental-dir=/bak/mysql-xback/2018-12-12-14-51-26/ /bak/mysql-xback/all-backup/
9.合并第二次模擬到全備份
innobackupex --apply-log --redo-only --incremental-dir=/bak/mysql-xback/2018-12-12-14-52-47/ /bak/mysql-xback/all-backup/
10.開始恢復
innobackupex --copy-back /bak/mysql-xback/all-backup/
11.添加權限并啟動
chown -R mysql.mysql /usr/local/mysql/data/
systemctl start mysql
12.查看數據恢復到125條,正常前是129條
mysql -uroot -p'123456' -e "use single;select count(*) from s1;"
13.查看備份時的pos點
cat /bak/mysql-xback/2018-12-12-14-52-47/xtrabackup_info | grep binlog_pos
顯示如下
binlog_pos = filename ‘mysql-bin.000003’, position ‘1509’
14.解壓最后2個binlog壓縮包
cd /bak/mysql-binback/
tar -xf mybak-section-2018-12-12-15-07.tar.gz
tar -xf mybak-section-2018-12-12-15-15.tar.gz
15.進入第二個包,它是在最后一次增量備份后才執行的binlog
cd mybak-section-2018-12-12-15-07
將1509pos點之前的行刪除,每個binlog文件前18行要保留
mysqlbinlog mysql-bin.000003 > 03.log
cat 03.log | grep -n 1509
恢復數據
cat 03.log | mysql -uroot -p'123456'
當前總是為128
mysql -uroot -p'123456' -e "use single;select count(*) from s1;"
16.進入倒數第一個包,它存放出問題之前的數據
cd mybak-section-2018-12-12-15-15
將drop這個有問題的指令之后的行刪除
mysqlbinlog mysql-bin.000004 > 04.log
cat 04.log | grep -n drop
恢復數據
cat 04.log | mysql -uroot -p'123456'
當前總是為129
mysql -uroot -p'123456' -e "use single;select count(*) from s1;"
五.重寫測試
進入到腳本目錄
cd/root/bin
執行重寫腳本
bash mybak-rewrite.sh可以看到原先目錄只有一個全備份ls /bak/mysql-xback/原先的全備份和增量備份的打包ls -lh /bak/xback/
總結
以上是生活随笔為你收集整理的mysql用sql语句怎么做个脚本备份_mysql备份脚本的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue 接口数据排序_Vue 使用 ax
- 下一篇: python车辆轨迹分析_Ngsim数据