Linux上自動備份MySQL
在資料庫表丟失或損壞的情況下,備份你的資料庫是很重要的。如果發生系統崩潰,你肯定想能夠將你的表儘可能丟失最少的資料恢復到崩潰發生時的狀態。本文主要對MyISAM表做備份恢復。
備份策略一:直接拷貝資料庫檔案
備份策略二:使用mysqldump備份資料庫(一個星期全備一次,每天增量備份)
一、 直接拷貝資料檔案
直接拷貝資料檔案最為直接、快速、方便,但缺點是基本上不能實現增量備份。為了保證資料的一致性,需要在備份檔案前,執行以下 SQL 語句:FLUSH TABLES WITH READ LOCK;也就是把記憶體中的資料都重新整理到磁碟中,同時鎖定資料表,以保證拷貝過程中不會有新的資料寫入。這種方法備份出來的資料恢復也很簡單,直接拷貝回原來的資料庫目錄下即可。
為了方便的拷貝出資料檔案,我寫了一個指令碼讓其每天執行一次做備份。在/目錄下建一個目錄用來放置指令碼檔案,
#mkdir /scripts
建立一個備份資料庫的一個指令碼檔案
#vi backup_mysql.sh
#!/bin/bash
backup_dir=/backup/databak #備份檔案放置目錄
backup_target_dir=/backup/db
backup_logs_dir=/backup/logs #備份日誌目錄
db=bcmedia
DATE=$(date +%Y%m%d)
#得到10天前的日期
ccDATE=$(date "-d 10 day ago" +%Y%m%d)
echo "開始複製資料表" >> $backup_logs_dir/$db$DATE
echo "-----------`date +"%Y-%m-%d %H:%M:%S"`--------------------" >> $backup_logs_dir/$db$DATE
cp -R /data/$db $backup_target_dir/ #mysql資料庫的資料目錄為/data
echo "開始壓縮資料表" >> $backup_logs_dir/$db$DATE
echo "------------------------" >> $backup_logs_dir/$db$DATE
cd $backup_target_dir
tar -zcvf $backup_dir/db$DATE.tar.gz $db/ >> $backup_logs_dir/$db$DATE
if [ $? -eq 0 ]
then
echo "backup succeed" >> $backup_logs_dir/$db$DATE
else
echo "backup fail" >> $backup_logs_dir/$db$DATE
fi
echo "開始刪除原資料表" >> $backup_logs_dir/$db$DATE
echo "-----------------------" >> $backup_logs_dir/$db$DATE
rm -rf $backup_target_dir/* && echo “刪除原資料表” >> $backup_logs_dir/$db$DATE
echo "刪除10天前資料" >>$backup_logs_dir/$db$DATE
if [ -e $backup_dir/db$ccDATE.tar.gz ]
then
rm -rf $backup_dir/db$ccDATE.tar.gz
echo "Delete $backup_dir/db$ccDATE.tar.gz succeed" >>$backup_logs_dir/$db$DATE
else
echo "Not found $backup_dir/db$ccDATE.tar.gz file" >>$backup_logs_dir/$db$DATE
fi
if [ -e $backup_logs_dir/$db$ccDATE ]
then
rm -rf $backup_logs_dir/$db$ccDATE
echo "Delete $backup_logs_dir/$db$ccDATE succeed" >>$backup_logs_dir/$db$DATE
else
echo "Not found $backup_logs_dir/$db$ccDATE file" >>$backup_logs_dir/$db$DATE
fi
儲存退出並新增可執行的許可權
#chmod 755 backup_mysql.sh
讓指令碼每天執行一次,每天備份一次資料庫,在crontab 裡面新增一行
Crontab –e
10 4 * * * /scripts/ backup_mysql.sh #每天4點10分執行指令碼備份資料庫
還原資料庫的時候只要把備份出的檔案拷貝到資料庫放置資料的目錄下,修改許可權。重啟下資料庫就完成了恢復了。
二、 使用mysqldump備份資料庫
mysqldump 是採用SQL級別的備份機制,它將資料表導成 SQL 指令碼檔案,在不同的 MySQL 版本之間升級時相對比較合適,這也是最常用的備份方法。關於mysqldump的更詳細解釋用/MysqlDir/bin/mysqldump –help 來檢視詳細的解釋。
我們使用的資料庫備份完成之後有10個G如果每天都做一次全備,不方便,就一個星期做一次全備,一天做一次增量備份。為了不影響線上業務,實現線上備份,並且能增量備份,最好的辦法就是採用主從複製機制(replication),在 slave 機器上做備份。詳細的mysqlreplication請參看mysql主主、主從複製詳解
一個星期一次的全備的指令碼,指令碼檔案放在/scripts目錄下,備份時需要一些目錄,注意需要手動建立。
#vi mysql_full_bak.sh
#!/bin/bash
# This is mysql mysqlfullbak scripts
#2009-08-20
#badboy
user=bak
passwd=123456
databak_dir=/backup/cacti #備份的目錄
eMailFile=$databak_dir/email.txt
DATE=`date +%Y%m%d`
logFile=$databak_dir/logs/mysql$DATE.log
database=cacti
echo " " > $eMailFile
echo "---------------------------------" >> $eMailFile
echo $(date +"%y-%m-%d %H:%M:%S") >> $eMailFile
cd /data
dumpFile=$database$DATE.sql
GZDumpFile=$database$DATE.tar.gz
options="-u$user -p$passwd --opt --extended-insert=false --triggers=false -R --hex-blob --flush-logs --delete-master-logs -B $database"
mysqldump $options > $dumpFile #匯出資料檔案
if [[ $? == 0 ]]; then
tar cvzf $GZDumpFile $dumpFile >> $eMailFile 2>&1
echo "BackupFileName:$GZDumpFile" >> $eMailFile
echo "DataBase Backup Success" >> $eMailFile
scp $GZDumpFile 地址”:/Dir #傳送備份檔案到另一臺計算機,需要做好ssh信任
rm -f $dumpFile #刪除備份的檔案
rm –rf $databak_dir/daily/* #刪除每天備份的檔案
else
echo "DataBase Backup Fail!" >> $emailFile
mail -s " DataBase Backup Fail " $eMail < $eMailFile #如果備份不成功傳送郵件通知
fi
echo "--------------------------------------------------------" >> $logFile
cat $eMailFile >> $logFile
更多mysqldump的選項請檢視mysqldump –help
每天增量備份的指令碼,定義為每天4點10分時執行此檔案,備份上一天4點10分之後到今天4點之前的資料
#vi mysqldailybak.sh
#!/bin/bash
# This is mysql mysqldailybak scripts
# 2009-08-20
# badboy
/usr/bin/mysqladmin flush-logs #
user=bak
passwd=123456
database=cacti
daily_databak_dir=$databak_dir/daily #備份目錄,需要建立
eMailFile=$daily_databak_dir/email.txt
DATE=`date +%Y%m%d`
logFile=$daily_databak_dir/mysql$DATE.log
echo " " > $eMailFile
echo "---------------------------------" >> $eMailFile
echo $(date +"%y-%m-%d %H:%M:%S") >> $eMailFile
echo "---------------------------------" >> $eMailFile
TIME=$(date "-d 10 day ago" +%Y%m%d%H%M%S)
StartTime=$(date "-d 1 day ago" +"%Y-%m-%d %H:%M:%S")
echo “Delete 10 days before the log ” >> $eMailFile
mysql -u$user -p"$passwd" -e "purge master logs before ${TIME}" && echo "delete 10 days before log" |tee -a $eMailFile #刪除10天前的2進位制檔案
filename=/data/`cat /data/mysql-bin.index |awk -F "/" '{print $2}'` # 2進位制檔案
for i in $filename
do
echo "$StartTime start backup binlog " >> $eMailFile
mysqlbinlog -u$user -p$passwd -d $batabase --start-datetime="$StartTime" $i >> $daily_databak_dir/daily$DATE |tee -a $eMailFile
done
if [ $? = 0 ]
then
cd $daily_databak_dir
tar -zcvf $daily_databak_dir/$database$DATE.tar.gz daily$DATE >>/dev/null 2>&1
#scp $daily_databak_dir/$database$DATE.tar.gz 地址”:/Dir #傳送備份檔案到另一臺計算機,需要做好ssh信任
echo "daily backup succeed" >> $eMailFile
else
echo "daily backup fail" >> $eMailFile
mail -s "MySQL Backup" $eMail < $eMailFile #備份失敗之後傳送郵件通知
fi
cat $eMailFile > $logFile
新增可執行的許可權
#chmod 755 /scripts/mysql_full_bak.sh /scripts/mysqldailybak.sh
加到crontab裡面讓指令碼自動執行,如果有專門用於備份的伺服器,可以利用ssh認證、scp命令,自動傳送到另一臺伺服器上,保證資料的安全。可以參看rsync引數詳解、利用ssh、rsync 實現資料的定時同步
#su –bak
#crontab –e
10 4 * * 1-6 /scripts/mysqldailybak.sh #禮拜一到禮拜六執行每天備份指令碼
10 4 * * 0 /scripts/mysql_full_bak.sh #禮拜天執行全備份的指令碼
如果想把備份之後的資料檔案,傳送到另一臺伺服器上,做好ssh信任之後把指令碼中紅色的哪行註釋去掉就行。需要更多scp的資料請檢視scp --help