במאמר הזה נסביר איך להגדיר תהליכי עבודה מתוזמנים של גיבויים שתואמים לאפליקציה ושל שחזור מערכת מנקודה מסוימת בזמן (PITR) למסדי נתונים בניהול עצמי שפועלים במכונות וירטואליות (VM) של Linux ב-Compute Engine.
כשמגבים עומסי עבודה של מסדי נתונים עם שמירת מצב (stateful) – כמו IBM Db2, SAP HANA, MySQL או PostgreSQL – תמונות מצב סטנדרטיות עם עקביות במקרה של קריסה שנוצרו על ידי Backup and DR יכולות לתעד את מסד הנתונים בזמן שהעסקאות עדיין מתבצעות. הטרנזקציות הלא שלמות האלה עלולות להשחית נתונים, להשאיר טבלאות במצבים לא עקביים ולדרוש שגרות ארוכות של תיקון מסד הנתונים בזמן שחזור לאחר קריסה. גיבויים עקביים של אפליקציות פותרים את הבעיות האלה על ידי שילוב עם הסוכן האורח של ה-VM כדי להשעות את מסד הנתונים, ואם רוצים, להקפיא את מערכת הקבצים לפני יצירת קובץ snapshot.
לפני שמתחילים
לפני שמגדירים גיבויים תואמי-אפליקציה, צריך לבצע את המשימות הבאות.
התפקידים הנדרשים
כדי לקבל את ההרשאות שנדרשות להגדרת גיבויים שתואמים לאפליקציה, בקשו מהאדמין להקצות לכם את התפקידים הבאים ב-IAM בפרויקט:
-
כדי להגדיר ולנהל תוכניות גיבוי:
משתמש גיבוי של Backup and DR (
roles/backupdr.backupUser) -
כדי לנהל מכונות של Compute Engine:
Compute Instance Admin (v1) (
roles/compute.instanceAdmin.v1) -
כדי לגשת לסודות של Secret Manager מסקריפטים:
מנהל גישה לסודות של Secret Manager (
roles/secretmanager.secretAccessor)
להסבר על מתן תפקידים, ראו איך מנהלים את הגישה ברמת הפרויקט, התיקייה והארגון.
יכול להיות שאפשר לקבל את ההרשאות הנדרשות גם באמצעות תפקידים בהתאמה אישית או תפקידים מוגדרים מראש.
דרישות מוקדמות
בדף לבחירת הפרויקט במסוף Google Cloud , בוחרים פרויקט ב-Google Cloud או יוצרים אותו.
מוודאים שהחיוב מופעל בפרויקט.
מפעילים את ממשקי ה-API של Backup and DR ו-Secret Manager.
מוודאים שקובצי הנתונים וקובצי היומן של מסד הנתונים מאוחסנים בדיסקים מתמידים רגילים. אי אפשר לבצע פעולות guest-flush בנפחי Google Cloud Hyperdisk.
אם אתם מתכננים להגדיר שחזור מערכת מנקודה מסוימת בזמן (PITR), הגדירו את מסד הנתונים כך שיעביר את יומני הטרנזקציות ויומני ה-Redo לארכיון ב-Persistent Disk נפרד וייעודי – לדוגמה, כזה שנטען ב-
/db2/ACT/log_archive.
שימוש במסגרת bring-your-own-script (BYOS) guest-flush
Backup and DR משתמש ב-framework של Bring-Your-Own-Script (BYOS) לניקוי נתונים במכונה אורחת כדי להשהות את מסד הנתונים לפני שנוצר קובץ snapshot. סביבת האורח מסתמכת על שני סקריפטים שנמצאים בספרייה /etc/google/snapshots/ במכונה הווירטואלית של Linux:
- Pre-snapshot script (
/etc/google/snapshots/pre.sh): הסקריפט שמופעל לפני שנוצר ה-snapshot. הסקריפט הזה צריך להשעות את פעולות מסד הנתונים, ואפשר גם להקפיא את מערכת הקבצים. - סקריפט אחרי קובץ snapshot (
/etc/google/snapshots/post.sh): מופעל אחרי שנוצר קובץ ה-snapshot. הסקריפט הזה צריך לבטל את ההקפאה של מערכת הקבצים ולהמשיך את פעולות מסד הנתונים.
למידע נוסף על תבניות סקריפטים ספציפיות למסדי נתונים, ראו סקריפטים לדוגמה לפי סוג מסד נתונים.
אופציונלי: הקפאה והפשרה של מערכות קבצים
הקפאת מערכת הקבצים באמצעות כלי השירות הרגיל של Linux fsfreeze היא אופציונלית ולא חובה. השבתת מסד הנתונים מבטיחה עקביות של טרנזקציות ברמת האפליקציה. עם זאת, אם אתם צריכים עקביות נוספת ברמת מערכת הקבצים, אתם יכולים לכלול בסקריפטים את הפקודות הבאות להקפאה ולביטול ההקפאה של מערכת הקבצים.
חשוב לוודא שהסקריפטים pre.sh ו-post.sh במכונה הווירטואלית מוגדרים לטפל בהקפאה אופציונלית של מערכת הקבצים לנפחי יומנים בלי להשעות את פעולות מסד הנתונים.
הוספת הוראות להקפאת מערכת הקבצים לקובץ pre.sh
אם בוחרים להקפיא מערכות קבצים, צריך להוסיף את לוגיקת הגילוי וההקפאה הבאה בסוף הסקריפט של pre.sh אחרי השהיית מסד הנתונים:
# Discover local writeable mount points
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
# FREEZE FILESYSTEMS (Optional)
for mnt in $MOUNT_POINTS; do
if ! sudo fsfreeze -f "$mnt"; then
logger "Error: Failed to freeze $mnt. Cleaning up..."
# Attempt emergency thaw
for thaw_mnt in $MOUNT_POINTS; do sudo fsfreeze -u "$thaw_mnt" 2>/dev/null; done
# Add your database-specific resume/cleanup commands here before exiting
exit 1
fi
logger "Filesystem $mnt is frozen."
done
הוספת הוראות לביטול ההקפאה של מערכת הקבצים לקובץ post.sh
אם אתם מקפיאים מערכות קבצים ב-pre.sh, הוסיפו את הלוגיקה הבאה לביטול ההקפאה בתחילת הסקריפט של post.sh לפני שתמשיכו את מסד הנתונים:
# Discover local writeable mount points
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
# UNFREEZE FILESYSTEMS (Optional)
for mnt in $MOUNT_POINTS; do
sudo fsfreeze -u "$mnt"
logger "Filesystem $mnt is unfrozen."
done
אחזור דינמי של פרטי כניסה באמצעות Secret Manager
אל תכתבו בקוד של סקריפטים של מעטפת סיסמאות או פרטי כניסה סטטיים למסד נתונים. במקום זאת, השתמשו ב-Secret Manager כדי לאחזר פרטי כניסה באופן דינמי בזמן הריצה. מחליפים את משתני הסיסמה הסטטיים בסקריפטים בלוגיקה הבאה:
# Fetch the database password from Secret Manager dynamically
DBPASSWORD=$(gcloud secrets versions access latest \
--secret="SECRET_NAME" \
--format='get(payload.data)' | tr -d '\n')
if [ $? -ne 0 ]; then
logger "Critical Error: Unable to fetch the password from Secret Manager."
exit 1
fi
מחליפים את SECRET_NAME בשם של הסוד ב-Secret Manager.
סקירת סקריפטים לדוגמה לפי סוג מסד הנתונים
בדוגמאות הבאות מוצגות הטמעות של pre.sh ו-post.sh למנועים נתמכים של מסדי נתונים שפועלים במכונות Linux.
IBM Db2
סקריפט לפני קבלת תמונת מצב (/etc/google/snapshots/pre.sh)
#!/bin/bash
# Location: /etc/google/snapshots/pre.sh
# 1. Define Mount Points for the Database
MOUNT_POINTS=("DATA_MOUNT_POINT" "LOG_MOUNT_POINT")
logger "BYOS Framework: Starting pre-snapshot script."
# 2. QUIESCE DATABASE (Generic Hook)
# Replace with DB-specific command (e.g., 'db2 set write suspend')
logger "Suspending Database I/O..."
# [INSERT DB QUIESCE COMMAND HERE]
# 3. FREEZE FILESYSTEMS (Optional)
for mnt in "${MOUNT_POINTS[@]}"; do
if ! sudo fsfreeze -f "$mnt"; then
logger "Error: Failed to freeze $mnt."
# Attempt emergency thaw
for thaw_mnt in "${MOUNT_POINTS[@]}"; do sudo fsfreeze -u "$thaw_mnt" 2>/dev/null; done
# [INSERT DB RESUME COMMAND HERE]
exit 1
fi
logger "Filesystem $mnt is frozen."
done
סקריפט לאחר קבלת תמונת המצב (/etc/google/snapshots/post.sh)
#!/bin/bash
# Location: /etc/google/snapshots/post.sh
MOUNT_POINTS=("DATA_MOUNT_POINT" "LOG_MOUNT_POINT")
logger "BYOS Framework: Starting post-snapshot script."
# 1. UNFREEZE FILESYSTEMS (Optional)
for mnt in "${MOUNT_POINTS[@]}"; do
sudo fsfreeze -u "$mnt"
logger "Filesystem $mnt is unfrozen."
done
# 2. RESUME DATABASE (Generic Hook)
# Replace with DB-specific command (e.g., 'db2 set write resume')
logger "Resuming Database I/O..."
# [INSERT DB RESUME COMMAND HERE]
logger "BYOS Framework: Cleanup complete."
Oracle
סקריפט לפני קבלת תמונת מצב (/etc/google/snapshots/pre.sh)
sudo mkdir -p /etc/google/snapshots
sudo tee /etc/google/snapshots/pre.sh > /dev/null << 'EOF'
#!/bin/bash
# Place Oracle (ASM) into hot backup mode before Backup and DR captures disks
su - oracle -c "sqlplus -s / as sysdba" << 'SQL'
WHENEVER SQLERROR EXIT FAILURE;
ALTER DATABASE BEGIN BACKUP;
EXIT;
SQL
if [ $? -ne 0 ]; then
echo "Error: Failed to place Oracle in backup mode. Aborting snapshot." >&2
exit 1
fi
EOF
sudo chmod 750 /etc/google/snapshots/pre.sh
סקריפט לאחר קבלת תמונת מצב (/etc/google/snapshots/post.sh)
sudo tee /etc/google/snapshots/post.sh > /dev/null << 'EOF'
#!/bin/bash
# Release Oracle from backup mode and archive current redo log to +FRA
su - oracle -c "sqlplus -s / as sysdba" << 'SQL'
WHENEVER SQLERROR EXIT FAILURE;
ALTER DATABASE END BACKUP;
ALTER SYSTEM ARCHIVE LOG CURRENT;
EXIT;
SQL
if [ $? -ne 0 ]; then
echo "Warning: Failed to execute ALTER DATABASE END BACKUP." >&2
exit 1
fi
EOF
sudo chmod 750 /etc/google/snapshots/post.sh
SAP HANA
סקריפט לפני קבלת תמונת מצב (/etc/google/snapshots/pre.sh)
#!/bin/bash
# Location: /etc/google/snapshots/pre.sh
DISK_ARG="$1"
# 1. Configuration & Discovery
DBSID="DBSID"
DBADM="DBADM"
ID_FILE="/tmp/hana_snapshot_id_$DBSID"
HDB_KEY="HDB_KEY"
if [[ "$DISK_ARG" == "," ]] || [[ "$DISK_ARG" == "1/0" ]] || [[ "$DISK_ARG" == "sda" ]]; then
# Dynamically discover all local writeable mount points for full VM image consistency
# Filters out pseudo, temporary, and read-only filesystems
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
logger "SAP HANA Full VM BYOS: Starting pre-snapshot script for $DBSID."
# 2. QUIESCE DATABASE (Create SAP HANA Snapshot)
logger "SAP HANA Full VM BYOS: Creating database snapshot..."
# Determine HANA Version
# Versions 2.0+ use 'FOR FULL SYSTEM' syntax
HANAVERSION=$(su - $DBADM -c "HDB version" | grep "version:" | awk '{print $2}' | cut -d'.' -f1)
if [ "$HANAVERSION" = "1" ]; then
SQL="BACKUP DATA CREATE SNAPSHOT COMMENT 'SNAPSHOT_$(date +%Y%m%d)'"
else
SQL="BACKUP DATA FOR FULL SYSTEM CREATE SNAPSHOT COMMENT 'SNAPSHOT_$(date +%Y%m%d)'"
fi
# Execute the snapshot command via hdbsql
su - $DBADM -c "hdbsql -j -U $HDB_KEY \"$SQL\""
if [ $? -ne 0 ]; then
logger "Error: Failed to create SAP HANA snapshot."
exit 1
fi
# Retrieve the BACKUP_ID for the prepared snapshot
ID=$(su - $DBADM -c "hdbsql -j -t -U $HDB_KEY \"SELECT BACKUP_ID FROM M_BACKUP_CATALOG WHERE STATE_NAME = 'prepared' ORDER BY SYS_START_TIME DESC\"" | head -n 2 | tr -d '"' | tail -n 1)
if [ -z "$ID" ]; then
logger "Error: Could not retrieve BACKUP_ID for prepared snapshot."
exit 1
fi
echo "$ID" > "$ID_FILE"
logger "SAP HANA Full VM BYOS: Database snapshot prepared with ID $ID."
fi
סקריפט לאחר קבלת תמונת מצב (/etc/google/snapshots/post.sh)
#!/bin/bash
# Location: /etc/google/snapshots/post.sh
DISK_ARG="$1"
# 1. Configuration & Discovery
DBSID="DBSID"
DBADM="DBADM"
ID_FILE="/tmp/hana_snapshot_id_$DBSID"
HDB_KEY="HDB_KEY"
if [[ "$DISK_ARG" == "," ]] || [[ "$DISK_ARG" == "1/0" ]] || [[ "$DISK_ARG" == "sda" ]]; then
# Discover all local writeable mount points to perform unfreeze
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
logger "SAP HANA Full VM BYOS: Starting post-snapshot script for $DBSID."
# 3. RESUME DATABASE (Close SAP HANA Snapshot)
if [ -f "$ID_FILE" ]; then
ID=$(cat "$ID_FILE")
logger "SAP HANA Full VM BYOS: Closing database snapshot ID $ID..."
# Determine HANA version for correct syntax
HANAVERSION=$(su - $DBADM -c "HDB version" | grep "version:" | awk '{print $2}' | cut -d'.' -f1)
if [ "$HANAVERSION" = "1" ]; then
SQL="BACKUP DATA CLOSE SNAPSHOT BACKUP_ID $ID SUCCESSFUL 'SNAPSHOT_COMPLETED'"
else
SQL="BACKUP DATA FOR FULL SYSTEM CLOSE SNAPSHOT BACKUP_ID $ID SUCCESSFUL 'SNAPSHOT_COMPLETED'"
fi
# Execute the close snapshot command
RESULT=$(su - $DBADM -c "hdbsql -j -U $HDB_KEY \"$SQL\"")
if [ $? -ne 0 ]; then
logger "Error: Failed to close SAP HANA snapshot. $RESULT"
else
logger "SAP HANA Full VM BYOS: Database snapshot closed successfully."
fi
# Cleanup the temporary ID file
rm -f "$ID_FILE"
else
logger "Error: Snapshot ID file not found. Manual intervention required to close HANA snapshot."
fi
logger "SAP HANA Full VM BYOS: Cleanup complete."
else
MOUNT_POINTS="/hanabackup"
for mnt in $MOUNT_POINTS; do
sudo fsfreeze -u "$mnt"
logger "Filesystem $mnt is unfrozen."
done
fi
מחליפים את מה שכתוב בשדות הבאים:
-
DBSID: מזהה המערכת (SID) של SAP HANA באותיות רישיות. -
DBADM: משתמש מערכת ההפעלה של האדמין ב-SAP HANA (למשל<sid>adm). -
HDB_KEY: המפתח של SAP HANA userstore שמוגדר לגישה למסד הנתונים.
SAP ASE
סקריפט לפני קבלת תמונת מצב (/etc/google/snapshots/pre.sh)
#!/bin/bash
# Location: /etc/google/snapshots/pre.sh
# 1. Configuration
OSUSER="OS_USER"
SYB_SERVER="SYB_SERVER_NAME"
SYB_USER="SYB_USER"
SYB_PASS="SYB_PASSWORD"
SYB_DBLIST="DATABASE_LIST"
TAG_NAME="SNAPSHOT_$(date +%Y%m%d)"
MANIFEST_DIR="/var/tmp/sybase_manifests" # Directory for manifest files
# 2. Discovery
# Dynamically discover local writeable mount points
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
logger "Sybase Full VM BYOS: Starting pre-snapshot script."
# 3. QUIESCE DATABASE
mkdir -p "$MANIFEST_DIR"
chown $OSUSER "$MANIFEST_DIR"
logger "Sybase Full VM BYOS: Quiescing databases: $SYB_DBLIST..."
# Command logic from act_sybase_pre.sh
# We use 'hold' to suspend activity and create the manifest file
su - $OSUSER -c "isql -U$SYB_USER -P$SYB_PASS -S$SYB_SERVER -X --retserverror" <<EOF
quiesce database $TAG_NAME hold $SYB_DBLIST for external dump to '$MANIFEST_DIR/manifest_$TAG_NAME.dat' with override
go
exit
EOF
if [ $? -ne 0 ]; then
logger "Error: Failed to quiesce Sybase databases."
exit 1
fi
# 4. FREEZE FILESYSTEMS (Optional)
for mnt in $MOUNT_POINTS; do
if ! sudo fsfreeze -f "$mnt"; then
logger "Error: Failed to freeze $mnt."
# Attempt emergency thaw
for thaw_mnt in $MOUNT_POINTS; do sudo fsfreeze -u "$thaw_mnt" 2>/dev/null; done
# Release the database quiesce
su - $OSUSER -c "isql -U$SYB_USER -P$SYB_PASS -S$SYB_SERVER -X" <<EOF
quiesce database $TAG_NAME release
go
exit
EOF
exit 1
fi
logger "Filesystem $mnt is frozen."
done
סקריפט לאחר קבלת תמונת מצב (/etc/google/snapshots/post.sh)
#!/bin/bash
# Location: /etc/google/snapshots/post.sh
# 1. Configuration
OSUSER="OS_USER"
SYB_SERVER="SYB_SERVER_NAME"
SYB_USER="SYB_USER"
SYB_PASS="SYB_PASSWORD"
TAG_NAME="SNAPSHOT_$(date +%Y%m%d)"
MANIFEST_DIR="/var/tmp/sybase_manifests"
# 2. Discovery
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
logger "Sybase Full VM BYOS: Starting post-snapshot script."
# 3. UNFREEZE FILESYSTEMS (Optional)
for mnt in $MOUNT_POINTS; do
sudo fsfreeze -u "$mnt"
logger "Filesystem $mnt is unfrozen."
done
# 4. RESUME DATABASE
logger "Sybase Full VM BYOS: Releasing databases for tag $TAG_NAME..."
# Command logic from act_sybase_post.sh
su - $OSUSER -c "isql -U$SYB_USER -P$SYB_PASS -S$SYB_SERVER -X" <<EOF
use master
go
quiesce database $TAG_NAME release
go
exit
EOF
if [ $? -ne 0 ]; then
logger "Error: Failed to release Sybase databases."
else
logger "Sybase Full VM BYOS: Databases released successfully."
# Cleanup manifest
rm -f "$MANIFEST_DIR/manifest_$TAG_NAME.dat"
fi
logger "Sybase Full VM BYOS: Cleanup complete."
מחליפים את מה שכתוב בשדות הבאים:
-
OS_USER: המשתמש במערכת ההפעלה שמריץ את SAP ASE (למשלsybase). -
SYB_SERVER_NAME: שם השרת של SAP ASE. -
SYB_USER: משתמש מסד הנתונים עם הרשאות להשהות מסדי נתונים. -
SYB_PASSWORD: הסיסמה של משתמש מסד הנתונים (או שליפה דינמית באמצעות Secret Manager). -
DATABASE_LIST: רשימה מופרדת בפסיקים של מסדי נתונים שרוצים להעביר למצב שקט.
SAP IQ
סקריפט לפני קבלת תמונת מצב (/etc/google/snapshots/pre.sh)
#!/bin/bash
# Location: /etc/google/snapshots/pre.sh
# 1. Configuration
OSUSER="OS_USER"
DB_NAME="DB_NAME"
CONN_STR="uid=DB_USER;pwd=DB_PASSWORD;dbn=$DB_NAME;eng=ENGINE_NAME"
BKP_DIR="/var/tmp/sybaseiq_bkp"
FULL_BKP_FILE="$BKP_DIR/FULL_VIR_DEC"
# 2. Discovery
# Dynamically discover all local writeable mount points for full VM consistency
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
logger "SybaseIQ Full VM BYOS: Starting pre-snapshot script."
# 3. QUIESCE DATABASE (Virtual Decoupled Backup)
mkdir -p "$BKP_DIR"
chown $OSUSER "$BKP_DIR"
logger "SybaseIQ Full VM BYOS: Preparing virtual decoupled backup..."
# Execute the quiesce command logic from act_sybaseiq_pre.sh
su -m $OSUSER -c "dbisql -nogui -c '$CONN_STR' \"BACKUP DATABASE FULL VIRTUAL DECOUPLED TO '$FULL_BKP_FILE'\""
if [ $? -ne 0 ]; then
logger "Error: Failed to freeze (not able to take full_vir_dec backup)."
exit 1
fi
# 4. FREEZE FILESYSTEMS (Optional)
for mnt in $MOUNT_POINTS; do
if ! sudo fsfreeze -f "$mnt"; then
logger "Error: Failed to freeze $mnt."
# Attempt emergency thaw
for thaw_mnt in $MOUNT_POINTS; do sudo fsfreeze -u "$thaw_mnt" 2>/dev/null; done
# Cleanup quiesce file as backup is invalid
rm -f "$FULL_BKP_FILE"
exit 1
fi
logger "Filesystem $mnt is frozen."
done
סקריפט לאחר קבלת תמונת מצב (/etc/google/snapshots/post.sh)
#!/bin/bash
# Location: /etc/google/snapshots/post.sh
# 1. Configuration
OSUSER="OS_USER"
DB_NAME="DB_NAME"
CONN_STR="uid=DB_USER;pwd=DB_PASSWORD;dbn=$DB_NAME;eng=ENGINE_NAME"
BKP_DIR="/var/tmp/sybaseiq_bkp"
FULL_BKP_FILE="$BKP_DIR/FULL_VIR_DEC"
INC_BKP_FILE="$BKP_DIR/INC_BKP"
# 2. Discovery
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
logger "SybaseIQ Full VM BYOS: Starting post-snapshot script."
# 3. UNFREEZE FILESYSTEMS (Optional)
for mnt in $MOUNT_POINTS; do
sudo fsfreeze -u "$mnt"
logger "Filesystem $mnt is unfrozen."
done
# 4. RESUME DATABASE (Post-Snapshot Cleanup)
logger "SybaseIQ Full VM BYOS: Performing incremental since full backup..."
# Logic from act_sybaseiq_post.sh to finish the decoupled sequence
su -m $OSUSER -c "dbisql -nogui -c '$CONN_STR' \"BACKUP DATABASE INCREMENTAL SINCE FULL TO '$INC_BKP_FILE'\""
if [ $? -ne 0 ]; then
logger "Error: Failed post-quiesce incremental backup."
fi
# Remove temporary files created during quiesce
rm -f "$FULL_BKP_FILE"*
logger "SybaseIQ Full VM BYOS: Cleanup complete."
מחליפים את מה שכתוב בשדות הבאים:
-
OS_USER: המשתמש במערכת ההפעלה שמריץ את SAP IQ (למשלsybiq). -
DB_NAME: השם של מסד הנתונים ב-SAP IQ. -
DB_USER: משתמש מסד הנתונים עם הרשאות DBA. -
DB_PASSWORD: הסיסמה של משתמש מסד הנתונים (או שליפה דינמית באמצעות Secret Manager). -
ENGINE_NAME: השם של המנוע של מסד הנתונים של SAP IQ.
SAP MaxDB
סקריפט לפני קבלת תמונת מצב (/etc/google/snapshots/pre.sh)
#!/bin/bash
# Location: /etc/google/snapshots/pre.sh
# 1. Configuration
DBSID="DBSID"
OSUSER="OS_USER"
MAXDB_KEY="-user DBM_USER,DBM_PASSWORD"
AUTOLOG_TMPLT="LOG_BACKUP"
# 2. Discovery
# Dynamically discover all local writeable mount points for full VM consistency
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
logger "MaxDB Full VM BYOS: Starting pre-snapshot script for $DBSID."
# 3. QUIESCE DATABASE
# Optional: Trigger a log backup first to ensure point-in-time recovery readiness
logger "MaxDB Full VM BYOS: Triggering log backup..."
su -m $OSUSER -c "dbmcli -d $DBSID $MAXDB_KEY -uUTL -c backup_start $AUTOLOG_TMPLT LOG"
# Suspend logwriter to quiesce the database
logger "MaxDB Full VM BYOS: Suspending logwriter..."
su -m $OSUSER -c "dbmcli -d $DBSID $MAXDB_KEY -uUTL -c util_execute suspend logwriter"
if [ $? -ne 0 ]; then
logger "Error: Failed to suspend MaxDB logwriter."
exit 1
fi
# 4. FREEZE FILESYSTEMS (Optional)
for mnt in $MOUNT_POINTS; do
if ! sudo fsfreeze -f "$mnt"; then
logger "Error: Failed to freeze $mnt."
# Attempt emergency thaw
for thaw_mnt in $MOUNT_POINTS; do sudo fsfreeze -u "$thaw_mnt" 2>/dev/null; done
# Resume the logwriter as the backup is no longer consistent
su -m $OSUSER -c "dbmcli -d $DBSID $MAXDB_KEY -uUTL -c util_execute resume logwriter"
exit 1
fi
logger "Filesystem $mnt is frozen."
done
סקריפט לאחר קבלת תמונת מצב (/etc/google/snapshots/post.sh)
#!/bin/bash
# Location: /etc/google/snapshots/post.sh
# 1. Configuration
DBSID="DBSID"
OSUSER="OS_USER"
MAXDB_KEY="-user DBM_USER,DBM_PASSWORD"
# 2. Discovery
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
logger "MaxDB Full VM BYOS: Starting post-snapshot script for $DBSID."
# 3. UNFREEZE FILESYSTEMS (Optional)
for mnt in $MOUNT_POINTS; do
sudo fsfreeze -u "$mnt"
logger "Filesystem $mnt is unfrozen."
done
# 4. RESUME DATABASE
logger "MaxDB Full VM BYOS: Resuming logwriter..."
su -m $OSUSER -c "dbmcli -d $DBSID $MAXDB_KEY -uUTL -c util_execute resume logwriter"
if [ $? -ne 0 ]; then
logger "Error: Failed to resume MaxDB logwriter."
else
logger "MaxDB Full VM BYOS: Logwriter resumed successfully."
fi
logger "MaxDB Full VM BYOS: Cleanup complete."
מחליפים את מה שכתוב בשדות הבאים:
-
DBSID: מזהה המערכת (SID) של SAP MaxDB באותיות רישיות. -
OS_USER: המשתמש במערכת ההפעלה שמריץ את MaxDB (למשלsdba). -
DBM_USER: המשתמש של מנהל מסד הנתונים (DBM). -
DBM_PASSWORD: הסיסמה של המשתמש ב-DBM (או שימוש במפתח DBM שמור:-k KEY_NAME).
PostgreSQL
סקריפט לפני קבלת תמונת מצב (/etc/google/snapshots/pre.sh)
#!/bin/bash
# 1. Configuration
OSUSER="OS_USER"
PG_HOME="PG_HOME"
DBUSER="DB_USER"
PORT=PORT_NUMBER
DBNAME="DB_NAME"
FIFO="/tmp/pg_backup_fifo_$PORT"
PID_FILE="/tmp/pg_backup_pid_$PORT"
ACT_JOBNAME="SNAPSHOT_$(date +%Y%m%d%H%M%S)"
# 2. Discovery
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
export PATH=$PG_HOME/bin:$PATH
logger "PostgreSQL Full VM BYOS: Starting pre-snapshot script."
# 3. QUIESCE DATABASE (Session-Bound)
rm -f "$FIFO"
mkfifo "$FIFO"
chown "$OSUSER" "$FIFO"
su "$OSUSER" -c "psql -p $PORT -U $DBUSER -d $DBNAME -f $FIFO" > /tmp/pg_backup_output.log 2>&1 &
echo $! > "$PID_FILE"
psql_version=$(su "$OSUSER" -c "psql --version" | awk '{print $3}' | cut -d'.' -f1)
if [ "$psql_version" -ge 15 ]; then
CMD="SELECT pg_backup_start('$ACT_JOBNAME');"
else
CMD="SELECT pg_start_backup('$ACT_JOBNAME');"
fi
echo "$CMD" > "$FIFO"
sleep 2
# 4. FREEZE FILESYSTEMS (Optional)
for mnt in $MOUNT_POINTS; do
if ! sudo fsfreeze -f "$mnt"; then
logger "Error: Failed to freeze $mnt. Cleaning up..."
for thaw_mnt in $MOUNT_POINTS; do sudo fsfreeze -u "$thaw_mnt" 2>/dev/null; done
echo "SELECT pg_backup_stop(); exit;" > "$FIFO"
rm -f "$FIFO" "$PID_FILE"
exit 1
fi
logger "Filesystem $mnt is frozen."
done
סקריפט לאחר קבלת תמונת מצב (/etc/google/snapshots/post.sh)
#!/bin/bash
PORT=PORT_NUMBER
FIFO="/tmp/pg_backup_fifo_$PORT"
PID_FILE="/tmp/pg_backup_pid_$PORT"
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
logger "PostgreSQL Full VM BYOS: Starting post-snapshot script."
# 1. UNFREEZE FILESYSTEMS (Optional)
for mnt in $MOUNT_POINTS; do
sudo fsfreeze -u "$mnt"
logger "Filesystem $mnt is unfrozen."
done
# 2. RESUME DATABASE (Close Session)
if [ -p "$FIFO" ]; then
logger "PostgreSQL Full VM BYOS: Closing backup session via FIFO..."
echo "SELECT pg_backup_stop(); SELECT pg_stop_backup(); exit;" > "$FIFO"
if [ -f "$PID_FILE" ]; then
wait "$(cat "$PID_FILE")" 2>/dev/null
fi
rm -f "$FIFO" "$PID_FILE"
logger "PostgreSQL Full VM BYOS: Database session closed."
else
logger "Error: FIFO not found. Session may have terminated unexpectedly."
fi
logger "PostgreSQL Full VM BYOS: Cleanup complete."
מחליפים את מה שכתוב בשדות הבאים:
-
OS_USER: המשתמש במערכת ההפעלה שמפעיל את PostgreSQL (למשלpostgres). -
PG_HOME: הנתיב לספריית ההתקנה של PostgreSQL. -
DB_USER: המשתמש במסד הנתונים של PostgreSQL עם הרשאות של משתמש-על. -
PORT_NUMBER: מספר היציאה ש-PostgreSQL מאזין לה (ברירת המחדל:5432). -
DB_NAME: שם מסד הנתונים שאליו רוצים להתחבר.
MySQL
סקריפט לפני קבלת תמונת מצב (/etc/google/snapshots/pre.sh)
#!/bin/bash
# 1. Configuration
DBUSER="DB_USER"
DBPASSWORD="DB_PASSWORD"
PORTNO=PORT_NUMBER
SOCKET_FILE="/var/run/mysqld/mysqld.sock"
MYSQL_PATH="/usr/bin/mysql"
FIFO="/tmp/mysql_backup_fifo_$PORTNO"
PID_FILE="/tmp/mysql_backup_pid_$PORTNO"
# 2. Discovery
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
logger "MySQL Full VM BYOS: Starting pre-snapshot script."
# 3. QUIESCE DATABASE (Session-Bound Lock)
rm -f "$FIFO"
mkfifo "$FIFO"
$MYSQL_PATH -u"$DBUSER" -p"$DBPASSWORD" -S"$SOCKET_FILE" -P"$PORTNO" < "$FIFO" > /tmp/mysql_backup_output.log 2>&1 &
echo $! > "$PID_FILE"
logger "MySQL Full VM BYOS: Issuing FLUSH TABLES WITH READ LOCK..."
echo "FLUSH TABLES WITH READ LOCK; SELECT SLEEP(86400);" > "$FIFO"
sleep 2
# 4. FREEZE FILESYSTEMS (Optional)
for mnt in $MOUNT_POINTS; do
if ! sudo fsfreeze -f "$mnt"; then
logger "Error: Failed to freeze $mnt. Cleaning up..."
for thaw_mnt in $MOUNT_POINTS; do sudo fsfreeze -u "$thaw_mnt" 2>/dev/null; done
kill $(cat "$PID_FILE") 2>/dev/null
rm -f "$FIFO" "$PID_FILE"
exit 1
fi
logger "Filesystem $mnt is frozen."
done
סקריפט לאחר קבלת תמונת מצב (/etc/google/snapshots/post.sh)
#!/bin/bash
PORTNO=PORT_NUMBER
FIFO="/tmp/mysql_backup_fifo_$PORTNO"
PID_FILE="/tmp/mysql_backup_pid_$PORTNO"
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
logger "MySQL Full VM BYOS: Starting post-snapshot script."
# 1. UNFREEZE FILESYSTEMS (Optional)
for mnt in $MOUNT_POINTS; do
sudo fsfreeze -u "$mnt"
logger "Filesystem $mnt is unfrozen."
done
# 2. RESUME DATABASE (Unlock)
if [ -f "$PID_FILE" ]; then
logger "MySQL Full VM BYOS: Releasing locks..."
kill $(cat "$PID_FILE") 2>/dev/null
rm -f "$FIFO" "$PID_FILE"
logger "MySQL Full VM BYOS: Locks released and session closed."
else
logger "Error: PID file not found. Lock may have been lost prematurely."
fi
logger "MySQL Full VM BYOS: Cleanup complete."
מחליפים את מה שכתוב בשדות הבאים:
-
DB_USER: משתמש מסד הנתונים של MySQL עם הרשאות אדמין. -
DB_PASSWORD: הסיסמה של מסד הנתונים ב-MySQL (או שליפה דינמית באמצעות Secret Manager). -
PORT_NUMBER: מספר היציאה ש-MySQL מאזין לה (ברירת המחדל:3306).
MariaDB
סקריפט לפני קבלת תמונת מצב (/etc/google/snapshots/pre.sh)
#!/bin/bash
# Location: /etc/google/snapshots/pre.sh
# 1. Configuration
DBUSER="DB_USER"
DBPASSWORD="DB_PASSWORD"
PORTNO=PORT_NUMBER
SOCKET_FILE="/var/run/mysqld/mysqld.sock"
MARIADB_PATH="/usr/bin/mariadb" # or /usr/bin/mysql
SRV_TYPE="Master" # Set to "Slave" for standby nodes
FIFO="/tmp/mariadb_backup_fifo_$PORTNO"
PID_FILE="/tmp/mariadb_backup_pid_$PORTNO"
STARTPOS_FILE="/tmp/STARTPOS_FILE_$PORTNO.txt"
# 2. Discovery
# Dynamically discover all local writeable mount points for full VM consistency
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
logger "MariaDB Full VM BYOS: Starting pre-snapshot script."
# 3. QUIESCE DATABASE (Session-Bound)
# Create a FIFO to hold the session open
rm -f "$FIFO"
mkfifo "$FIFO"
# Start a background mariadb session that reads from the FIFO
# This keeps the session (and locks) active until the process is killed
$MARIADB_PATH -u"$DBUSER" -p"$DBPASSWORD" -S"$SOCKET_FILE" -P"$PORTNO" < "$FIFO" > /tmp/mariadb_backup_output.log 2>&1 &
echo $! > "$PID_FILE"
# Prepare quiesce query (Logic from act_mariadb_pre.sh)
if [ "$SRV_TYPE" != "Slave" ]; then
# Primary node: lock all tables
logger "MariaDB Full VM BYOS: Issuing FLUSH TABLES WITH READ LOCK..."
echo "FLUSH TABLES WITH READ LOCK; SELECT SLEEP(86400);" > "$FIFO"
# Capture master status for PITR/replication info
$MARIADB_PATH -u"$DBUSER" -p"$DBPASSWORD" -S"$SOCKET_FILE" -P"$PORTNO" -e "SHOW MASTER STATUS;" > "$STARTPOS_FILE"
else
# Replica node: stop the slave thread
logger "MariaDB Full VM BYOS: Issuing STOP SLAVE..."
echo "STOP SLAVE; SELECT SLEEP(86400);" > "$FIFO"
# Capture slave status
$MARIADB_PATH -u"$DBUSER" -p"$DBPASSWORD" -S"$SOCKET_FILE" -P"$PORTNO" -e "SHOW SLAVE STATUS \G;" > "$STARTPOS_FILE"
fi
# Wait a brief moment to ensure the command is processed
sleep 2
# 4. FREEZE FILESYSTEMS (Optional)
for mnt in $MOUNT_POINTS; do
if ! sudo fsfreeze -f "$mnt"; then
logger "Error: Failed to freeze $mnt. Cleaning up..."
# Attempt emergency thaw
for thaw_mnt in $MOUNT_POINTS; do sudo fsfreeze -u "$thaw_mnt" 2>/dev/null; done
# Kill the background session to release locks
kill $(cat "$PID_FILE") 2>/dev/null
rm -f "$FIFO" "$PID_FILE"
exit 1
fi
logger "Filesystem $mnt is frozen."
done
סקריפט לאחר קבלת תמונת מצב (/etc/google/snapshots/post.sh)
#!/bin/bash
# Location: /etc/google/snapshots/post.sh
# 1. Configuration
PORTNO=PORT_NUMBER
SRV_TYPE="Master"
DBUSER="DB_USER"
DBPASSWORD="DB_PASSWORD"
SOCKET_FILE="/var/run/mysqld/mysqld.sock"
MARIADB_PATH="/usr/bin/mariadb"
FIFO="/tmp/mariadb_backup_fifo_$PORTNO"
PID_FILE="/tmp/mariadb_backup_pid_$PORTNO"
# 2. Discovery
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
logger "MariaDB Full VM BYOS: Starting post-snapshot script."
# 3. UNFREEZE FILESYSTEMS (Optional)
for mnt in $MOUNT_POINTS; do
sudo fsfreeze -u "$mnt"
logger "Filesystem $mnt is unfrozen."
done
# 4. RESUME DATABASE
if [ -f "$PID_FILE" ]; then
logger "MariaDB Full VM BYOS: Resuming database operations..."
# Kill the background sleep process to automatically release session-bound locks
kill $(cat "$PID_FILE") 2>/dev/null
# For slave nodes, explicitly ensure replication is started
if [ "$SRV_TYPE" = "Slave" ]; then
$MARIADB_PATH -u"$DBUSER" -p"$DBPASSWORD" -S"$SOCKET_FILE" -P"$PORTNO" -e "START SLAVE;"
fi
rm -f "$FIFO" "$PID_FILE"
logger "MariaDB Full VM BYOS: Cleanup complete."
else
logger "Error: PID file not found. Database state might be inconsistent."
fi
מחליפים את מה שכתוב בשדות הבאים:
-
DB_USER: המשתמש במסד הנתונים של MariaDB עם הרשאות אדמין. -
DB_PASSWORD: הסיסמה למסד הנתונים של MariaDB (או שליפה דינמית באמצעות Secret Manager). -
PORT_NUMBER: מספר היציאה ש-MariaDB מאזינה לה (ברירת המחדל:3306).
פריסת סקריפטים של guest-flush
אחרי שמכינים את הסקריפטים pre.sh ו-post.sh למסד הנתונים, פורסים אותם במכונה הווירטואלית של Linux:
מתחברים למכונה הווירטואלית של Linux שבה פועל מסד הנתונים בניהול עצמי באמצעות SSH.
יוצרים את הספרייה
/etc/google/snapshots/אם היא עדיין לא קיימת:sudo mkdir -p /etc/google/snapshotsשומרים את הסקריפטים המותאמים אישית של
pre.shו-post.shבספרייה/etc/google/snapshots/במכונה הווירטואלית.מוודאים שלסקריפטים יש הרשאות הפעלה:
sudo chmod 755 /etc/google/snapshots/pre.sh /etc/google/snapshots/post.sh
הפעלת סוכן האורח לתמונות מצב
כדי לאפשר ל-Backup and DR להריץ סקריפטים לפני ואחרי יצירת קובץ snapshot, צריך להפעיל את שילוב ה-snapshot בסביבת האורח של Compute Engine במכונה הווירטואלית של Linux:
מתחברים למכונה הווירטואלית של Linux שבה פועל מסד הנתונים בניהול עצמי באמצעות SSH (אם עדיין לא התחברתם).
פותחים את קובץ התצורה של סביבת האורח בכלי לעריכת טקסט:
sudo nano /etc/default/instance_configs.cfgכדי להפעיל את תמונות המצב, מוסיפים או משנים את ההגדרות הבאות בקטע
[Snapshots]:[Snapshots] enabled = true timeout_in_seconds = 120מפעילים מחדש את סוכן האורח במכונה הווירטואלית כדי להחיל את השינויים:
sudo systemctl restart google-guest-agent
הגדרת תוכנית הגיבוי
אחרי שמגדירים במכונה הווירטואלית את הסקריפטים של guest-flush ומפעילים את הסוכן של המכונה האורחת בשביל תמונות המצב, מגדירים תוכנית גיבוי במסוף Google Cloud :
נכנסים לדף Backup and DR במסוף Google Cloud .
בתפריט הניווט, בוחרים באפשרות Backup Plans.
לוחצים על Create Backup Plan, או בוחרים תוכנית גיבוי קיימת ולוחצים על Edit.
בשלבי ההגדרה של Instance Backup, מאתרים את אפשרויות העקביות.
בוחרים באפשרות Enable Application Consistency.
שומרים את תוכנית הגיבוי ומחילים אותה על המכונה הווירטואלית. לפי לוח הזמנים, תוכנית הגיבוי מפעילה את סוכן האורח כדי להריץ את הסקריפט
pre.sh, ליצור את קובץ ה-Snapshot ולהריץ את הסקריפטpost.sh.
הגדרת הגיבוי של Persistent Disk לשחזור מסד הנתונים מנקודה מסוימת בזמן (PITR)
במסדי נתונים בניהול עצמי כמו Db2 ו-SAP HANA, אתם יכולים להגדיר גיבויים נפרדים של Persistent Disk כדי לתעד את יומני הארכיון של מסד הנתונים, וכך לאפשר שחזור מערכת מנקודה מסוימת בזמן (PITR). אם אתם לא צריכים שחזור מערכת מנקודה מסוימת בזמן (PITR), אתם יכולים לדלג לקטע השבתת הסקריפטים של guest-flush.
שיטות מומלצות לגיבויים של יומני שחזור מערכת מנקודה מסוימת בזמן (PITR)
תדירות: מגדירים את לוח הזמנים של תוכנית הגיבוי לדיסק הייעודי של היומן כך שיהיה זהה לרמת הפירוט של יומן השחזור מנקודה מסוימת בזמן (PITR), למשל כל 15 דקות או כל שעה.
אופטימיזציה של עלויות: אחסון של קובצי snapshot בתדירות גבוהה יכול להגדיל את עלויות האחסון. כדי לצמצם את התקורה, מגדירים את תקופת השמירה המינימלית ואת תקופת השמירה בכספת ללא שינויים התואמת לזמן המינימלי המותר שעדיין עומד בדרישות של חלון השחזור מנקודה מסוימת בזמן (PITR).
שחזור מסד נתונים בניהול עצמי לנקודת זמן ספציפית
אם הגדרתם גיבויים קבועים של מכונות וירטואליות לצד גיבויים ייעודיים של יומני Persistent Disk, אתם יכולים לפעול לפי ההליך הזה כדי לשחזר את מסד הנתונים לנקודת זמן ספציפית. אם לא הגדרתם גיבויים ייעודיים של יומנים או שאתם לא צריכים שחזור מערכת מנקודה מסוימת בזמן (PITR), אתם יכולים לשחזר את המכונה הווירטואלית ישירות לפי ההוראות במאמר שחזור מכונה של Compute Engine מכספת גיבוי, ולדלג לקטע ביצוע משימות אחרי השחזור.
תהליך העבודה של השחזור
שחזור ה-VM הבסיסי: בוחרים את הגיבוי של המכונה (תמונת מכונה) מכספת הגיבוי שקודמת לזמן היעד לשחזור. משחזרים אותו לפי הליכי השחזור הרגילים של Compute Engine. איך משחזרים מכונה של Compute Engine מכספת גיבוי
אם לא הגדרתם גיבויים ייעודיים של יומנים או שאתם לא צריכים שחזור מערכת מנקודה מסוימת בזמן (PITR), דלגו לשלב 4.
צירוף דיסקים של יומנים: מזהים ומשחזרים את קובצי ה-snapshot הרלוונטיים של דיסקים של יומנים שנוצרו עד לזמן היעד לשחזור. מחברים את הדיסקים החדשים שנוצרו למכונה ששוחזרה.
הרצה קדימה של מסד הנתונים: מתחברים למכונה ששוחזרה באמצעות SSH ומריצים את פקודת ההרצה קדימה הספציפית למסד הנתונים, כמו
ROLLFORWARD DATABASEב-Db2, באמצעות היומנים שנמצאים בדיסקים הקבועים שצורפו לאחרונה.ביצוע משימות אחרי השחזור: מבצעים את כל השלבים הספציפיים למסד הנתונים שנדרשים כדי להפעיל את האפליקציה.
השבתת סקריפטים של ניקוי מטמון של אורחים
כדי להסיר את הסקריפטים המותאמים אישית לניקוי המטמון של האורח ולהשבית את העקביות של האפליקציה:
ביטול ההקצאה של תוכנית הגיבוי למכונה: במסוף Google Cloud , נכנסים לדף Backup and DR, מאתרים את המכונה הווירטואלית בקטע Protected Resources ומבטלים את ההקצאה או מוחקים את השיוך של תוכנית הגיבוי.
הסרת הסקריפטים של guest-flush: מתחברים למכונת ה-VM של Linux באמצעות SSH ומסירים את הסקריפטים המותאמים אישית של guest-flush:
sudo rm -f /etc/google/snapshots/pre.sh /etc/google/snapshots/post.shהשבתת השילוב של קובץ snapshot בסוכן האורח: פותחים את
/etc/default/instance_configs.cfgבמכונה הווירטואלית, מגדירים אתenabled = falseבקטע[Snapshots]ומפעילים מחדש את הסוכן האורח:sudo systemctl restart google-guest-agent
המאמרים הבאים
- יצירה וניהול של תוכניות גיבוי
- מעקב אחרי משימות גיבוי ושחזור
- גיבוי מכונות של Compute Engine
- שחזור מכונות של Compute Engine
- גיבוי דיסקים לאחסון מתמיד (persistent disk)
- שחזור Persistent Disk