در محیطهای عملیاتی، یکی از نیازهای همیشگی مدیران پایگاهداده تهیه نسخه پشتیبان منطقی (logical backup) از طریق ابزار Data Pump است. گاهی سازمانها ترجیح میدهند علاوه بر بکاپ فیزیکی یا RMAN، به صورت روزانه یا هفتگی از کل دیتابیس دامپ تهیه کنند. از سوی دیگر، نگرانی از پر شدن فضای ذخیرهسازی هم وجود دارد. اگر روند بکاپگیری ادامه یابد اما کنترل نشود، دیر یا زود دیسک پر میشود و سرویسها دچار اختلال خواهند شد. بنابراین بهتر است مکانیزمی طراحی شود که دامپهای قدیمیتر از تعداد یا تاریخ مشخص، به صورت خودکار حذف شوند.
ساختار کلی اسکریپت
در این سناریو، هدف ما اجرای روزانه بکاپ کامل دیتابیس با ابزار expdp و نگهداری فایلها در مسیر مشخص (مثلاً /backup) است. پس از اتمام عملیات و اطمینان از موفقیت آن، فایلها به یک سرور NFS منتقل میشوند تا نسخهای دیگر نیز در محل جداگانه نگهداری شود. سپس دامپها و فایلهای لاگ قدیمیتر از ده روز از هر دو مسیر محلی و NFS حذف خواهند شد تا فضا کنترلشده باقی بماند.
مقاله ای برای راه اندازی nfs بر روی سایت وجود دارد:
https://vahiddb.com/fa/os/os-infra/setting-up-nfs-server-on-virtualbox-fa?highlight=WyJuZnMiXQ==
نکته مهم در این اسکریپت این است که ابتدا بررسی میشود آیا بکاپ واقعاً با موفقیت انجام شده است یا خیر. در فایل لاگ Data Pump معمولاً عبارت "successfully completed" ثبت میشود که با استفاده از دستور grep میتوان صحت عملیات را تأیید کرد. فقط در صورت موفقیت دامپ، عملیات حذف فایلهای قدیمی اجرا میشود تا در صورت بروز خطا، هیچ فایلی به اشتباه حذف نشود.
ضرورت تنظیم پارامترهای محیطی
چون این اسکریپت معمولاً تحت cron اجرا میشود، باید پارامترهای محیطی اوراکل به صورت کامل در ابتدای اسکریپت تنظیم شوند. زمانی که یک کاربر از طریق محیط shell به صورت عادی وارد سیستم میشود، فایلهایی مثل .bash_profile یا .bashrc بارگذاری میشوند و در نتیجه متغیرهایی مثل ORACLE_HOME، ORACLE_SID و PATH بهدرستی تنظیم میشوند. اما در زمان اجرای خودکار از طریق crontab، این فایلها بارگذاری نمیشوند و محیط کاملاً خالی است. به همین دلیل دستوراتی مثل expdp یا sqlplus شناخته نمیشوند و اسکریپت با خطای command not found مواجه میشود. برای جلوگیری از این خطا، باید در ابتدای اسکریپت تمام متغیرهای لازم بهصورت دستی export شوند. به عنوان مثال:
export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=/u01/app/oracle/product/19c/dbhome
export LD_LIBRARY_PATH=/u01/app/oracle/product/19c/dbhome/lib
export ORACLE_SID=vahidcdb
بدون این تنظیمات، cron نمیداند محیط اجرایی اوراکل کجاست و اسکریپت عملاً هیچ کاری انجام نخواهد داد.
مدیریت حجم و حذف دامپهای قدیمی
برای کنترل حجم، در اسکریپت از دستور find استفاده میشود تا فایلهایی که بیش از ده روز از آخرین تغییر آنها گذشته است حذف شوند. این کار بر اساس زمان mtime انجام میشود. مثلاً دستور زیر تمام فایلهای دامپ و لاگ قدیمیتر از ده روز را حذف میکند:
find /backup -name "DB-*.dmp" -mtime +10 -type f -exec rm -f {} \;
find /backup -name "DB-*.log" -mtime +10 -type f -exec rm -f {} \;
find /nfsbackup -name "DB-*.dmp" -mtime +10 -type f -exec rm -f {} \;
find /nfsbackup -name "DB-*.log" -mtime +10 -type f -exec rm -f {} \;
پارامتر +10 به این معناست که هر فایلی که بیش از ده روز از آخرین تغییر آن گذشته باشد حذف شود. در این روش، نیازی به شمارش تعداد فایلها نیست و سیستم به صورت خودکار بر اساس زمان آخرین تغییر عمل میکند.
#!/bin/bash
# ==============================================================
# Oracle Daily Data Pump Backup Script (with 10-day cleanup)
# Author: Vahid Nowrouzi (vahiddb.com)
# Version: 1.1
# Description:
# - Take full dump in /backup
# - Copy successful dump to /nfsbackup
# - Delete dump files older than 10 days if latest backup is successful
# ==============================================================
# ==== Environment Variables ====
export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=/u01/app/oracle/product/19c/dbhome
export LD_LIBRARY_PATH=/u01/app/oracle/product/19c/dbhome/lib
export ORACLE_SID=vahidcdb
export ORACLE_PATH=/u01/app/oracle/sql
export PATH=$PATH:$ORACLE_HOME/bin/
DATE=$(date '+%Y%m%d_%H%M%S')
LOCAL_DIR=/backup/dailydumpvahid
NFS_DIR=/nfsbackup
DMP_PREFIX=vahidPDB-${DATE}
LOG_FILE=${LOCAL_DIR}/${DMP_PREFIX}.log
# ==== Start Data Pump ====
echo "[$(date)] Starting Data Pump Export..."
$ORACLE_HOME/bin/expdp dumper/"od5j9MT_JcmTc7bHiuI4D"@vahidpdb full=y directory=backup dumpfile=${DMP_PREFIX}-%U.dmp logfile=${DMP_PREFIX}.log parallel=4 compression=all
SUCCESS=$(grep -i "successfully completed" "${LOG_FILE}" | wc -l)
if [ $SUCCESS -gt 0 ]; then
echo "[$(date)] Backup completed successfully."
# ==== Copy to NFS ====
echo "[$(date)] Copying dump and log to NFS..."
cp -p ${LOCAL_DIR}/${DMP_PREFIX}*.dmp ${NFS_DIR}/ 2>/dev/null
cp -p ${LOCAL_DIR}/${DMP_PREFIX}.log ${NFS_DIR}/ 2>/dev/null
# Local cleanup
find ${LOCAL_DIR} -name "${DMP_PREFIX}-*.dmp" -mtime +10 -type f -exec rm -f {} \;
find ${LOCAL_DIR} -name "${DMP_PREFIX}-*.log" -mtime +10 -type f -exec rm -f {} \;
# NFS cleanup
find ${NFS_DIR} -name "${DMP_PREFIX}-*.dmp" -mtime +10 -type f -exec rm -f {} \;
find ${NFS_DIR} -name "${DMP_PREFIX}-*.log" -mtime +10 -type f -exec rm -f {} \;
echo "[$(date)] Cleanup completed for both local and NFS."
else
echo "[$(date)] Backup failed. Check ${LOG_FILE}"
fi
echo "[$(date)] Script finished."
exit 0
در انتها هم این اسکریپت رو با دستور crontab -e به crontab اضافه می کنیم:
00 02 * * * /backup/dailydumpsearch/dailydumpsearchscript.sh
بعد با زدن wq: اون رو ذخیره می کنیم.