分享幾個數據庫備份腳本

備份腳本六個注意點

在寫腳本前我這裏按照個人習慣大概總結了以下六點,感興趣的可以繼續看看,不感興趣的直接跳過就好。

  1. 首先要注意的一點就是 shell 環境是 bash 還是 sh ,需要在你的腳本開頭中註明。

#!/bin/bash
  1. 其次就是數據庫環境變量需要申明,例如直接加載  .bash_profile 或者單獨申明 ORACLE_HOME、ORACLE_BASE 等。

source /home/oracle/.bash_profile

或者
ORACLE_BASE=/u01/app/oracle
ORACLE_HOME=/u01/app/product/11.2.0/dbhome_1
ORACLE_SID=JiekeXu1
ORACLE_USER=oracle
ORACLE_GROUP=oinstall
  1. 接下來就是定義相關備份目錄、日誌目錄等全局通用目錄。

DICPATH=/db_backup/oracle/rman

LOGPATH=$DICPATH/log
DATPATH=$DICPATH/data
  1. 到這裏呢纔算開始正式的備份任務,使用數據庫備份工具編寫備份腳本。

rman target / 

mysqldump ......
  1. 備份完成需要考慮存放日期,存放一週,兩週,或者 scp、ftp 等傳到遠程異地,然後考慮清理本地的磁盤空間。

--清理備份產生的日誌
find ${DIR}/log -name ${NAME}\* -mtime +90 | xargs rm -f
--清理備份集
--使用操作系統命令直接刪除備份集
find ${DIR}/data -name ${NAME}\* -mtime +30 | xargs rm -f
  1. 這一步就是部署備份了,一般藉助操作系統的 crontab 定時任務來搞定。

crontab 命令的語法

crontab [-u username] [-l|-e|-r]
選項與參數:
-u :只有 root 才能進行這個任務,亦即幫其他使用者創建/移除 crontab 工作排程;
-e :編輯 crontab 的工作內容
-l :查閱 crontab 的工作內容
-r :移除所有的 crontab 的工作內容,若僅要移除一項,請用 -e 去編輯


*    *    *    *    *
-    -    -    -    -
|    |    |    |    |
|    |    |    |    +----- 星期中的星期幾 (0 - 6) (星期天爲 0)
|    |    |    +---------- 月份 (1 - 12) 
|    |    +--------------- 一個月中的第幾天 (1 - 31)
|    +-------------------- 小時 (0 - 23)
+------------------------- 分鐘 (0 - 59)
另外關於 crontab 還有幾點要注意的:

定時任務添加註釋
>/dev/null 2>&1   ==>  &>/dev/null,別隨意打印日誌文件
定時任務裏面的程序腳本儘量用全路徑
避免不必要的程序以及命令輸出
定時任務之前添加註釋

下面看幾個 crontab 的例子。


0 */2 * * * /sbin/service httpd restart  意思是每兩個小時重啓一次apache 

50 7 * * * /sbin/service sshd start  意思是每天7:50開啓ssh服務 

50 22 * * * /sbin/service sshd stop  意思是每天22:50關閉ssh服務 

0 0 1,15 * * fsck /home  每月1號和15號檢查/home 磁盤 

1 * * * * /home/jieke/backup  每小時的第一分執行 /home/jieke/backup這個文件 

00 03 * * 1-5 find /home/oracle "*.xxx" -mtime +4 -exec rm {} \;  每週一至週五3點鐘,在目錄 /home/oracle 中,查找文件名爲*.xxx的文件,並刪除4天前的文件。

30 6 */10 * * ls  意思是每月的1、11、21、31日是的6:30執行一次ls命令

下面正式分享幾個腳本。 Oracle rman 增備腳本

vim  /home/oracle/scripts/oracle_rman.sh

#!/bin/bash
source /home/oracle/.bash_profile

DICPATH=/db_backup/oracle/rman

LOGPATH=$DICPATH/log
DATPATH=$DICPATH/data

if [ ! -d $LOGPATH ]; then
        mkdir -p $LOGPATH
fi

if [ ! -d $DATPATH ]; then
        mkdir -p $DATPATH
fi

if [ "$1" = "full" ]; then
echo 'jxrt'
rman target /  nocatalog msglog=$LOGPATH/rman_db_`date '+%Y%m%d%H%M%S'`.log <<EOF
run{
REPORT OBSOLETE;
#crosscheck archivelog all;
allocate channel c1 type disk;
allocate channel c2 type disk;
allocate channel c3 type disk;
allocate channel c4 type disk;
allocate channel c5 type disk;
allocate channel c6 type disk;
allocate channel c7 type disk;
allocate channel c8 type disk;
sql 'alter system archive log current';
backup as compressed  backupset incremental level 0 cumulative database FILESPERSET 8 tag 'dbfull' format '$DATPATH/full_%d_%T_%s_%U.bak' ;
sql 'alter system archive log current';
backup as compressed backupset archivelog all tag 'arch' format '$DATPATH/arch_%d_%T_%s_%U.arc';
DELETE force NOPROMPT OBSOLETE  recovery window of 8 days device type disk;
delete noprompt expired backup;
delete noprompt expired archivelog all;
backup current controlfile format '$DATPATH/ctl_%d_%T_%s_%U.bak'; 
release channel c1;
release channel c2;
release channel c3;
release channel c4;
release channel c5;
release channel c6;
release channel c7;
release channel c8;
}
exit;
EOF

elif [ "$1" = "diff" ]; then
rman target /  nocatalog msglog=$LOGPATH/rman_db_`date '+%Y%m%d%H%M%S'`.log <<EOF
run{
REPORT OBSOLETE;
#crosscheck archivelog all;
allocate channel c1 type disk;
allocate channel c2 type disk;
allocate channel c3 type disk;
allocate channel c4 type disk;
allocate channel c5 type disk;
allocate channel c6 type disk;
allocate channel c7 type disk;
allocate channel c8 type disk;
sql 'alter system archive log current';
backup as compressed  backupset incremental level 1 cumulative database FILESPERSET 8 tag 'dbincrL1' format '$DATPATH/incr_L1_%d_%T_%s_%U.bak' ;
sql 'alter system archive log current';
backup as compressed backupset archivelog all tag 'arch' format '$DATPATH/arch_%d_%T_%s_%U.arc';
DELETE force NOPROMPT OBSOLETE  recovery window of 8 days device type disk;
delete noprompt expired backup;
delete noprompt expired archivelog all;
backup current controlfile format '$DATPATH/ctl_%d_%T_%s_%U.bak';
release channel c1;
release channel c2;
release channel c3;
release channel c4;
release channel c5;
release channel c6;
release channel c7;
release channel c8;
}
exit;
EOF
fi

#oracle 用戶下的定時備份任務,可加參數 full 或者 diff
#30 0 * * * sh /home/oracle/db/scripts/oracle_rman.sh full

運行腳本
每週五凌晨 2:10 分運行 rman 腳本進行數據庫全備,注意後面加參數 full;
其他時間每天 2:22 分運行 rman 腳本進行數據庫增量備份,注意後面加參數 diff。

10 2 * * 5 /bin/bash /home/oracle/scripts/oracle_rman.sh full
22 2 * * 6,0,1,2,3,4 /bin/bash /home/oracle/scripts/oracle_rman.sh diff

Oracle rman 全備腳本 下面的腳本是對數據庫進行全備或者歸檔日誌備份的,注意如果使用到了 catlog 的話,也可以使用我註釋掉的 rman target catlog 連接串。


vim rman_nfs_bak.sh


#!/bin/bash

# ---------------------------------------------------------------------
#                       hot_database_backup_proxy.sh
# ---------------------------------------------------------------------
#  This script uses Recovery Manager to take a hot (inconsistent) database
#  backup. A hot backup is inconsistent because portions of the database are
#  being modified and written to the disk while the backup is progressing.
#  You must run your database in ARCHIVELOG mode to make hot backups. It is
#  assumed that this script will be executed by user root. In order for RMAN
#  to work properly we switch user (su -) to the oracle dba account before
#  execution. If this script runs under a user account that has Oracle dba
#  privilege, it will be executed using this user's account.
# ---------------------------------------------------------------------

ORACLE_USER=oracle
ORACLE_GROUP=oinstall
TARGET_CONNECT_STR=/
ORACLE_SID=JIEKEDB2
BAK_DIR=/backup/DB_Bak

source /home/${ORACLE_USER}/.bash_profile
# ---------------------------------------------------------------------
# Get the directory where the script locates and create log directory.
# ---------------------------------------------------------------------

DIR=$(cd `dirname ${0}`; pwd)
if [ ! -d ${DIR}/logs ]
then
mkdir -p ${DIR}/logs
chown -R ${ORACLE_USER}:${ORACLE_GROUP} ${DIR}/logs
fi

# ---------------------------------------------------------------------
# Get the variables we need from the local instance.
# ---------------------------------------------------------------------

SID=`ps -ef|grep pmon|grep ora_|awk -F'_' '{print $NF}'`
case "$SID" in
     "$ORACLE_SID")   RCVCAT_CONNECT_STR=jieke/jieke0jiekeR#@catalog
                      ;;
    *) echo "Cannot get SID,database is not running" >> ${DIR}/logs/`basename ${0}`_error.out
exit 1
       ;;
esac

# ---------------------------------------------------------------------
# Determine the user which is executing this script.
# ---------------------------------------------------------------------

CUSER=`whoami`
if [ ${CUSER} != ${ORACLE_USER} ]
then
echo "Please user oracle_user to run the script!" >> ${DIR}/logs/`basename ${0}`_error.out
exit 1
fi


# ---------------------------------------------------------------------
# Put output in <this file name>.out. Change as desired.
# Note: output directory requires write permission.
# ---------------------------------------------------------------------

case "$1" in
     "arch") RMAN_LOG_FILE=${ORACLE_SID}_arch_`date +%Y%m%d-%H%M%S`.out
     ;;
     "full") RMAN_LOG_FILE=${ORACLE_SID}_full_`date +%Y%m%d-%H%M%S`.out
     ;;
     *) echo " The following word is needed as a script parameter: arch or full! ">> ${DIR}/logs/`basename ${0}`_error.out
exit 1
       ;;
esac

NAME=`basename ${0}`
RMAN_LOG_FILE=${DIR}/logs/`basename $RMAN_LOG_FILE`
find ${DIR}/logs -name ${NAME}\* -mtime +30 | xargs rm -f
if [ -h ${DIR}/logs/last ]
then
rm ${DIR}/logs/last
fi
ln -s $RMAN_LOG_FILE ${DIR}/logs/last


# ---------------------------------------------------------------------
# You may want to delete the output file so that backup information does
# not accumulate.  If not, delete the following lines.
# ---------------------------------------------------------------------

# if [ -f "$RMAN_LOG_FILE" ]
# then
#     rm -f "$RMAN_LOG_FILE"
# fi

# -----------------------------------------------------------------
# Initialize the log file.
# -----------------------------------------------------------------

echo>> $RMAN_LOG_FILE
chmod 666 $RMAN_LOG_FILE

# ---------------------------------------------------------------------
# Log the start of this script.
# ---------------------------------------------------------------------

echo Script $0 >> $RMAN_LOG_FILE
echo ==== started on `date '+%a,%Y%m%d-%H:%M:%S'` ==== >> $RMAN_LOG_FILE
echo>> $RMAN_LOG_FILE

# ---------------------------------------------------------------------
# Print out the value of the variables set by this script.
# ---------------------------------------------------------------------

echo>> $RMAN_LOG_FILE
echo   "RMAN: $RMAN" >> $RMAN_LOG_FILE
echo   "ORACLE_SID: $ORACLE_SID" >> $RMAN_LOG_FILE
echo   "ORACLE_USER: $ORACLE_USER" >> $RMAN_LOG_FILE
echo   "ORACLE_HOME: $ORACLE_HOME" >> $RMAN_LOG_FILE

# Convert requests for incremental into archive log only backups
if [ "$1" = "arch" ]; then
echo "Archive log only backup requested" >> $RMAN_LOG_FILE
CMD_STR="
#rman target $TARGET_CONNECT_STR catalog $RCVCAT_CONNECT_STR log $RMAN_LOG_FILE append << EOF
rman target / log $RMAN_LOG_FILE append << EOF
RUN {
sql 'alter system archive log current';
ALLOCATE CHANNEL ch00 device type DISK;
BACKUP
    FILESPERSET 5
    FORMAT '${BAK_DIR}/arch_%d_%s_%p_%t'
    ARCHIVELOG ALL;
RELEASE CHANNEL ch00;
}
EOF
"
elif [ "$1" = "full" ]; then
echo "Full database backup requested" >> $RMAN_LOG_FILE
CMD_STR="
rman target $TARGET_CONNECT_STR catalog $RCVCAT_CONNECT_STR log $RMAN_LOG_FILE append << EOF
RUN {
ALLOCATE CHANNEL ch00 device type DISK;
ALLOCATE CHANNEL ch01 device type DISK;
BACKUP
   TAG ${ORACLE_SID}_hot_backup
   FILESPERSET 5
   FORMAT '${BAK_DIR}/database_%d_%s_%p_%t'
   DATABASE;
sql 'alter system archive log current';
RELEASE CHANNEL ch00;
RELEASE CHANNEL ch01;
}
EOF
"
fi

# Initiate the command string
sh -c "$CMD_STR"
#sh -c "$CMD_STR" >> $RMAN_LOG_FILE
RSTAT=$?
# ---------------------------------------------------------------------
# Log the completion of this script.
# ---------------------------------------------------------------------

if [ "$RSTAT" = "0" ]
then
    LOGMSG="ended successfully"
else
    LOGMSG="ended in error"
fi

echo>> $RMAN_LOG_FILE
echo Script $0 >> $RMAN_LOG_FILE
echo ==== $LOGMSG on `date '+%a,%Y%m%d-%H:%M:%S'` ==== >> $RMAN_LOG_FILE
echo>> $RMAN_LOG_FILE

exit $RSTAT

運行腳本

每週一凌晨 1:10 分運行 rman 腳本進行數據庫全備,注意後面加參數 full;
其他時間每天 0:10 分運行 rman 腳本進行數據庫歸檔日誌備份,注意後面加參數 arch。


10 1 * * 1 /home/oracle/db/scripts/rman_nfs_bak.sh full
10 0 * * * /home/oracle/db/scripts/rman_nfs_bak.sh arch

Oracle 歸檔刪除腳本

vi /home/oracle/clear_arch.sh

#!/bin/bash
ORACLE_BASE=/u01/app/oracle
ORACLE_HOME=/u01/app/product/19.0.0/dbhome_1
ORACLE_SID=jiekexu

PATH=$PATH:$ORACLE_HOME/bin/
source /home/oracle/.bash_profile

rman target / log=/home/oracle/clear_arch.log<<EOF
delete force noprompt archivelog all completed before 'sysdate-5';
exit
EOF

運行腳本
chmod +x /home/oracle/clear_arch.sh
每隔六個小時運行一次,清理五天之前的歸檔日誌。注意有備庫或者 ogg 的需要格外注意,避免被過早的刪除。

crontab -e
0 0,6,12,18 * * * /home/oracle/clear_arch.sh

 

MySQL xtrabackup 全備/增備腳本

more /home/mysql/scripts/backup.sh

#!/bin/bash

echo ""
START_TIME=`date`
echo "############## backup start at $START_TIME ##############"
echo ""
###you need install xtrabackup!###
# Set env
source /home/mysql/.bash_profile
which xtrabackup
# Database Info
DB_USER="root"
DB_PASS="R00t@123"
#HOST="127.0.0.1"
#PORT="24801"
CONF="/data/mysqldb/conf/mysql.conf"
SOCKET="/data/mysqldb/socket/mysql.sock"
# Databases to backup
# DB_NAME=("db1" "db2" "db3")
# Others
BAK_BASE="/db_bak/mysql_bak/mysql"
DATE=`date +%F`
YESTERDAY=`date +%F -d "-1 days"`
WEEK_DAY=`date +%w`
BAK_DIR=$BAK_BASE/$DATE-$WEEK_DAY
# Create Directory and backup
if [ "$WEEK_DAY" == "6"  ]; then
  xtrabackup --defaults-file=$CONF --socket=$SOCKET --backup --user=$DB_USER --password=$DB_PASS --target-dir=$BAK_DIR --compress
elif [ "$WEEK_DAY" == "0"  ]; then
  INCRE_BASE=$BAK_BASE/$YESTERDAY-6
  xtrabackup --defaults-file=$CONF --socket=$SOCKET --backup --user=$DB_USER --password=$DB_PASS --target-dir=$BAK_DIR --incremental-basedir=$INCRE_BASE --compress
else
        INCRE_BASE=$BAK_BASE/$YESTERDAY-$[WEEK_DAY-1]
  xtrabackup --defaults-file=$CONF --socket=$SOCKET --backup --user=$DB_USER --password=$DB_PASS --target-dir=$BAK_DIR --incremental-basedir=$INCRE_BASE --compress
fi
# TODO
#for var in ${DB_NAME[@]};
#do
#  xtrabackup --defaults-file=$CONF --socket=$SOCKET --backup --databases $var --user=$DB_USER --password=$DB_PASS --target-dir=$BAK_DIR --compress
#done
echo ""
END_TIME=`date`
echo "############## backup end at $END_TIME ##############"
echo ""

 


vim  /home/mysql/scripts/cleanup.sh

#!/bin/bash

echo ""
START_TIME=`date`
echo "############## clean up start at $START_TIME ##############"
echo ""

find /db_bak/mysql_bak/mysql -maxdepth 1 -type d -mtime +30
find /db_bak/mysql_bak/mysql -maxdepth 1 -type d -mtime +30 -exec rm -rf {} \;

echo ""
END_TIME=`date`
echo "############## clean up end at $END_TIME ##############"
echo ""
運行腳本

每天凌晨 0:10 分清理 30 天之前的備份,每天 0:30 分使用 xtrabackup 進行備份,注意只有週六是全備,其他時間均是增備。


10 0 * * * /home/mysql/scripts/cleanup.sh >> /home/mysql/scripts/cleanup.log 2>&1
30 0 * * * /home/mysql/scripts/backup.sh >> /home/mysql/scripts/backup.log 2>&1

MySQL mysqldump 備份腳本 1


#!/bin/bash

# 定義變量
DB_USER="root"
DB_PASS="password"
DB_NAME="database_name"
BACKUP_DIR="/db_backup/mysql"
REMOTE_SERVER="remote_server_address"
REMOTE_DIR="/db_backup/mysql"

# 創建備份目錄
if [ ! -d $BACKUP_DIR ]; then
  mkdir -p $BACKUP_DIR
fi

# 備份數據庫
mysqldump -u$DB_USER -p$DB_PASS $DB_NAME > $BACKUP_DIR/$DB_NAME-$(date +%Y%m%d).sql

# 壓縮備份文件
tar -czvf $BACKUP_DIR/$DB_NAME-$(date +%Y%m%d).tar.gz $BACKUP_DIR/$DB_NAME-$(date +%Y%m%d).sql

# 上傳備份文件到遠程服務器
scp $BACKUP_DIR/$DB_NAME-$(date +%Y%m%d).tar.gz $REMOTE_SERVER:$REMOTE_DIR

# 刪除過期備份文件
find $BACKUP_DIR -type f -name "*.tar.gz" -mtime +15 -delete

MySQL mysqldump 備份腳本 2

vim mysql_backup.sh

#!/bin/bash
#完成數據庫的定時備份
#備份的路徑
BACKUP=/db_backup/backup/db
#當前的時間作爲文件名
DATETIME=$(date +%Y_%m_%d_%H%M%S)
#可以輸出變量調試
#echo ${DATETIME}
echo "==========開始備份==========="
echo "備份的路徑是 $BACKUP/$DATETIME.tar.gz"

#主機
HOST=localhost
#用戶名
DB_USER=root
#密碼
DB_PWD=root
#備份數據庫名
DATABASE=mysql
#創建備份的路徑
#如果備份的路徑文件夾存在就使用,否則創建
[ ! -d "$BACKUP/$DATETIME"  ]  && mkdir -p "$BACKUP/$DATETIME" 
#執行mysql的備份數據庫的指令
mysqldump -u${DB_USER} -p${DB_PWD} --host=$HOST  $DATABASE | gzip  > $BACKUP/$DATETIME/$DATETIME.sql.gz
#打包備份文件
cd $BACKUP
tar -zcvf  $DATETIME.tar.gz  $DATETIME
#刪除臨時目錄
rm -rf  $BACKUP/$DATETIME

#刪除15天前的備份文件(-exec rm -rf {} \是固定寫法,刪除查詢出來的數據)
find $BACKUP -mtime +15 -name  "*.tar.gz" -exec rm -rf {} \;
echo "==========備份完成==========="

MySQL mysqldump 備份腳本 3


vim mysql_backup.sh

#!/bin/bash
#全備方式,一般在從機上執行,適用於小中型mysql數據庫
#刪除15天以前備份

source /etc/profile        #加載系統環境變量
source ~/.bash_profile    #加載用戶環境變量
set -o nounset             #引用未初始化變量時退出
#set -o errexit            #執行shell命令遇到錯誤時退出

user="root"
password="root"
host="localhost"
port="13306"
#需備份的數據庫,數組
db=("test")
#備份時加鎖方式,
#MyISAM爲鎖表--lock-all-tables,
#InnoDB爲鎖行--single-transaction
lock="--single-transaction"
mysql_path="/usr/local/mysql"
backup_path="${mysql_path}/backup"
date=$(date +%Y-%m-%d_%H-%M-%S)
day=15
backup_log="${mysql_path}/backup.log"

#建立備份目錄
if [ ! -e $backup_path ];then
    mkdir -p $backup_path
fi

#刪除以前備份
find $backup_path -type f -mtime +$day -exec rm -rf {} \; > /dev/null 2>&1

echo "開始備份數據庫:${db[*]}"

#備份並壓縮
backup_sql(){
    dbname=$1
    backup_name="${dbname}_${date}.sql"
    #-R備份存儲過程,函數,觸發器
    mysqldump -h $host -P $port -u $user -p$password $lock --default-character-set=utf8 --flush-logs -R $dbname > $backup_path/$backup_name    
    if [[ $? == 0 ]];then
        cd $backup_path
        tar zcpvf $backup_name.tar.gz $backup_name
        size=$(du $backup_name.tar.gz -sh | awk '{print $1}')
        rm -rf $backup_name
        echo "$date 備份 $dbname($size) 成功 "
    else
        cd $backup_path
        rm -rf $backup_name
        echo "$date 備份 $dbname 失敗 "
    fi
}

#循環備份
length=${#db[@]}
for (( i = 0; i < $length; i++ )); do
        backup_sql ${db[$i]} >> $backup_log 2>&1
done

echo "備份結束,結果查看 $backup_log"
du $backup_path/*$date* -sh | awk '{print "文件:" $2 ",大小:" $1}'

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章