Configurer des sauvegardes cohérentes avec l'application

Ce document explique comment configurer des workflows de sauvegarde planifiée et cohérente avec les applications, ainsi que de récupération à un moment précis pour les bases de données autogérées exécutées sur des instances de machine virtuelle (VM) Linux Compute Engine.

Lorsque vous sauvegardez des charges de travail de base de données avec état, telles qu'IBM Db2, SAP HANA, MySQL ou PostgreSQL, les instantanés standards cohérents en cas de plantage pris par Backup and DR peuvent capturer la base de données pendant que les transactions sont toujours en cours. Ces transactions incomplètes peuvent corrompre les données, laisser les tables dans des états incohérents et nécessiter de longues routines de réparation de base de données lors de la récupération après un plantage. Les sauvegardes cohérentes avec les applications résolvent ces problèmes en s'intégrant à l'agent invité de la VM pour mettre la base de données au repos et, éventuellement, geler le système de fichiers avant de créer un instantané.

Avant de commencer

Effectuez les tâches suivantes avant de configurer des sauvegardes cohérentes avec les applications.

Rôles requis

Pour obtenir les autorisations nécessaires afin de configurer des sauvegardes cohérentes avec les applications, demandez à votre administrateur de vous accorder les rôles IAM suivants sur votre projet :

Pour en savoir plus sur l'attribution de rôles, consultez Gérer l'accès aux projets, aux dossiers et aux organisations.

Vous pouvez également obtenir les autorisations requises via des rôles personnalisés ou d'autres rôles prédéfinis.

Prérequis

  1. Dans la Google Cloud console, sur la page de sélection du projet, sélectionnez ou créez un Google Cloud projet.

    Accéder au sélecteur de projet

  2. Vérifiez que la facturation est activée pour votre projet.

    Découvrez comment vérifier que la facturation est activée.

  3. Activez les API Backup and DR et Secret Manager.

    Activer les API

  4. Assurez-vous que les données de votre base de données et les fichiers journaux sont stockés sur des disques persistants standards Persistent Disks. Les volumes Google Cloud Hyperdisk ne sont pas compatibles avec les opérations guest-flush.

  5. Si vous prévoyez de configurer la récupération à un moment précis, configurez votre base de données pour archiver ses journaux de transactions et de restauration sur un disque persistant dédié et distinct, par exemple, monté sur /db2/ACT/log_archive.

Utiliser le framework guest-flush BYOS (Bring Your Own Script)

Backup and DR utilise le framework guest-flush BYOS (Bring Your Own Script) pour mettre votre base de données au repos avant de prendre un instantané. L'environnement invité s'appuie sur deux scripts résidant dans le répertoire /etc/google/snapshots/ de votre instance de VM Linux :

  • Script pré-instantané (/etc/google/snapshots/pre.sh) : s'exécute avant la prise de l'instantané. Ce script doit mettre les opérations de base de données au repos et peut éventuellement geler le système de fichiers.
  • Script post-instantané (/etc/google/snapshots/post.sh) : s'exécute après la prise de l'instantané. Ce script doit éventuellement dégeler le système de fichiers et reprendre les opérations de base de données.

Pour en savoir plus sur les modèles de script spécifiques à la base de données, consultez Examiner des exemples de scripts par type de base de données.

Facultatif : Geler et dégeler les systèmes de fichiers

Le gel du système de fichiers à l'aide de l'utilitaire Linux standard fsfreeze est facultatif et non obligatoire. La mise au repos de votre base de données garantit la cohérence des transactions au niveau de l'application. Toutefois, si vous avez besoin d'une cohérence supplémentaire au niveau du système de fichiers, vous pouvez éventuellement inclure les commandes de gel et de dégel du système de fichiers suivantes dans vos scripts.

Assurez-vous que vos scripts pre.sh et post.sh sur la VM sont configurés pour gérer le gel facultatif du système de fichiers pour les volumes de journaux sans suspendre les opérations de base de données.

Ajouter des instructions de gel du système de fichiers à pre.sh

Si vous choisissez de geler les systèmes de fichiers, ajoutez la logique de découverte et de gel suivante à la fin de votre script pre.sh après avoir mis la base de données au repos :

# 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

Ajouter des instructions de dégel du système de fichiers à post.sh

Si vous gelez les systèmes de fichiers dans pre.sh, ajoutez la logique de dégel suivante au début de votre script post.sh avant de reprendre la base de données :

# 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

Récupérer les identifiants de manière dynamique avec Secret Manager

Évitez de coder en dur les identifiants ou mots de passe de base de données statiques dans vos scripts shell. Utilisez plutôt Secret Manager pour récupérer les identifiants de manière dynamique au moment de l'exécution. Remplacez les variables de mot de passe statiques dans vos scripts par la logique suivante :

# 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

Remplacez SECRET_NAME par le nom du secret dans Secret Manager.

Examiner des exemples de scripts par type de base de données

Les exemples suivants fournissent des implémentations pre.sh et post.sh pour les moteurs de base de données compatibles exécutés sur des instances Linux.

IBM Db2

Script pré-instantané (/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

Script post-instantané (/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

Script pré-instantané (/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

Script post-instantané (/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

Script pré-instantané (/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

Script post-instantané (/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

Remplacez les éléments suivants :

  • DBSID : identifiant système SAP HANA (SID) en majuscules.
  • DBADM : utilisateur du système d'exploitation de l'administrateur SAP HANA (par exemple, <sid>adm).
  • HDB_KEY : clé du magasin d'utilisateurs SAP HANA configurée pour l'accès à la base de données.

SAP ASE

Script pré-instantané (/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

Script post-instantané (/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."

Remplacez les éléments suivants :

  • OS_USER : utilisateur du système d'exploitation exécutant SAP ASE (par exemple, sybase).
  • SYB_SERVER_NAME : nom du serveur SAP ASE.
  • SYB_USER : utilisateur de la base de données disposant des autorisations nécessaires pour mettre les bases de données au repos.
  • SYB_PASSWORD : mot de passe de l'utilisateur de la base de données (ou récupération dynamique avec Secret Manager).
  • DATABASE_LIST : liste de bases de données à mettre au repos, séparées par une virgule.

SAP IQ

Script pré-instantané (/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

Script post-instantané (/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."

Remplacez les éléments suivants :

  • OS_USER : utilisateur du système d'exploitation exécutant SAP IQ (par exemple, sybiq).
  • DB_NAME : nom de la base de données SAP IQ.
  • DB_USER : utilisateur de la base de données disposant de privilèges DBA.
  • DB_PASSWORD : mot de passe de l'utilisateur de la base de données (ou récupération dynamique avec Secret Manager).
  • ENGINE_NAME : nom du moteur de base de données SAP IQ.

SAP MaxDB

Script pré-instantané (/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

Script post-instantané (/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."

Remplacez les éléments suivants :

  • DBSID : identifiant système SAP MaxDB (SID) en majuscules.
  • OS_USER : utilisateur du système d'exploitation exécutant MaxDB (par exemple, sdba).
  • DBM_USER : utilisateur du gestionnaire de base de données (DBM).
  • DBM_PASSWORD : mot de passe de l'utilisateur DBM (ou utilisation d'une clé DBM stockée : -k KEY_NAME).

PostgreSQL

Script pré-instantané (/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

Script post-instantané (/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."

Remplacez les éléments suivants :

  • OS_USER : utilisateur du système d'exploitation exécutant PostgreSQL (par exemple, postgres).
  • PG_HOME : chemin d'accès au répertoire d'installation de PostgreSQL.
  • DB_USER : utilisateur de la base de données PostgreSQL disposant de privilèges de superutilisateur.
  • PORT_NUMBER : numéro de port sur lequel PostgreSQL écoute (par défaut : 5432).
  • DB_NAME : nom de la base de données à laquelle se connecter.

MySQL

Script pré-instantané (/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

Script post-instantané (/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."

Remplacez les éléments suivants :

  • DB_USER : utilisateur de la base de données MySQL disposant de privilèges d'administrateur.
  • DB_PASSWORD : mot de passe de la base de données MySQL (ou récupération dynamique avec Secret Manager).
  • PORT_NUMBER : numéro de port sur lequel MySQL écoute (par défaut : 3306).

MariaDB

Script pré-instantané (/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

Script post-instantané (/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

Remplacez les éléments suivants :

  • DB_USER : utilisateur de la base de données MariaDB disposant de privilèges d'administrateur.
  • DB_PASSWORD : mot de passe de la base de données MariaDB (ou récupération dynamique avec Secret Manager).
  • PORT_NUMBER : numéro de port sur lequel MariaDB écoute (par défaut : 3306).

Déployer des scripts guest-flush

Après avoir préparé vos scripts pre.sh et post.sh pour votre base de données, déployez-les sur l'instance de VM Linux :

  1. Connectez-vous à l'instance de VM Linux exécutant votre base de données autogérée à l'aide de SSH.

  2. Créez le répertoire /etc/google/snapshots/ s'il n'existe pas déjà :

    sudo mkdir -p /etc/google/snapshots
    
  3. Enregistrez vos scripts pre.sh et post.sh personnalisés dans le répertoire /etc/google/snapshots/ de l'instance de VM.

  4. Assurez-vous que les scripts disposent d'autorisations d'exécution :

    sudo chmod 755 /etc/google/snapshots/pre.sh /etc/google/snapshots/post.sh
    

Activer l'agent invité pour les instantanés

Pour autoriser Backup and DR à exécuter des scripts pré-instantané et post-instantané, activez l'intégration d'instantanés dans l'environnement invité Compute Engine sur votre instance de VM Linux :

  1. Connectez-vous à l'instance de VM Linux exécutant votre base de données autogérée à l'aide de SSH (si ce n'est pas déjà fait).

  2. Ouvrez le fichier de configuration de l'environnement invité dans un éditeur de texte :

    sudo nano /etc/default/instance_configs.cfg
    
  3. Ajoutez ou modifiez les paramètres suivants dans la section [Snapshots] pour activer les instantanés :

    [Snapshots]
    enabled = true
    timeout_in_seconds = 120
    
  4. Redémarrez l'agent invité sur l'instance de VM pour appliquer les modifications :

    sudo systemctl restart google-guest-agent
    

Configurer le plan de sauvegarde

Maintenant que l'instance de VM est configurée avec les scripts guest-flush et que l'agent invité est activé pour les instantanés, configurez un plan de sauvegarde dans la Google Cloud console :

  1. Dans la Google Cloud console, accédez à la page Backup and DR.

    Accéder à Backup and DR

  2. Dans le menu de navigation, sélectionnez Plans de sauvegarde.

  3. Cliquez sur Créer un plan de sauvegarde ou sélectionnez un plan de sauvegarde existant, puis cliquez sur Modifier.

  4. Dans les étapes de configuration Sauvegarde d'instance, recherchez les options de cohérence.

  5. Sélectionnez l'option Activer la cohérence des applications.

  6. Enregistrez et appliquez le plan de sauvegarde à votre instance de VM. Selon la programmation, le plan de sauvegarde déclenche l'agent invité pour exécuter votre script pre.sh, prendre l'instantané et exécuter le script post.sh.

Configurer la sauvegarde de disque persistant pour la récupération à un moment précis de la base de données

Pour les bases de données autogérées telles que Db2 et SAP HANA, vous pouvez configurer des sauvegardes de disque persistant autonomes pour capturer les journaux d'archive de la base de données, ce qui permet la récupération à un moment précis. Si vous n'avez pas besoin de la récupération à un moment précis, vous pouvez passer à Désactiver les scripts guest-flush.

Bonnes pratiques pour les sauvegardes de journaux de récupération à un moment précis

  • Fréquence : configurez la programmation du plan de sauvegarde pour ce disque de journaux dédié afin qu'elle soit égale à la granularité de votre journal de récupération à un moment précis, par exemple, toutes les 15 minutes ou toutes les heures.

  • Optimisation des coûts : le stockage d'instantanés fréquents peut augmenter les coûts de stockage. Pour minimiser les frais généraux, configurez la période de conservation minimale et la période de coffre d'immuabilité correspondante sur la durée minimale autorisée qui satisfait toujours votre fenêtre de récupération à un moment précis.

Récupérer une base de données autogérée à un moment précis

Si vous avez configuré des sauvegardes régulières de VM ainsi que des sauvegardes de journaux de disque persistant dédiées, suivez cette procédure pour restaurer votre base de données à un moment précis. Si vous n'avez pas configuré de sauvegardes de journaux dédiées ou si vous n'avez pas besoin de la récupération à un moment précis, consultez Restaurer une instance Compute Engine à partir d'un coffre-fort de sauvegarde pour restaurer directement votre VM, puis passez à Effectuer des tâches post-restauration.

Workflow de récupération

  1. Restaurer la VM de base : sélectionnez la sauvegarde d'instance (image de machine) du coffre-fort de sauvegarde qui précède votre heure de récupération cible. Restaurez-la en suivant les procédures de restauration Compute Engine standards. Pour obtenir des instructions, consultez Restaurer une instance Compute Engine à partir d'un coffre-fort de sauvegarde.

    Si vous n'avez pas configuré de sauvegardes de journaux dédiées ou si vous n'avez pas besoin de la récupération à un moment précis, passez à l'étape 4.

  2. Associer des disques de journaux : identifiez et restaurez les instantanés de disque de journaux pertinents capturés jusqu'à votre heure de récupération cible. Associez ces disques nouvellement créés à l'instance restaurée.

  3. Restaurer la base de données : connectez-vous à l'instance restaurée à l'aide de SSH et exécutez la commande de restauration spécifique à la base de données, telle que ROLLFORWARD DATABASE dans Db2, à l'aide des journaux situés sur les disques persistants nouvellement associés.

  4. Effectuer des tâches post-restauration : effectuez toutes les étapes spécifiques à la base de données requises pour mettre l'application en ligne.

Désactiver les scripts guest-flush

Pour supprimer les scripts guest-flush personnalisés et désactiver la cohérence des applications :

  1. Dissociez le plan de sauvegarde de votre instance: dans la Google Cloud console, accédez à la page Backup and DR, recherchez votre instance de VM sous Ressources protégées, puis dissociez ou supprimez l'association du plan de sauvegarde.

  2. Supprimez les scripts guest-flush: connectez-vous à votre instance de VM Linux à l'aide de SSH et supprimez les scripts guest-flush personnalisés :

    sudo rm -f /etc/google/snapshots/pre.sh /etc/google/snapshots/post.sh
    
  3. Désactivez l'intégration d'instantanés dans l'agent invité: ouvrez /etc/default/instance_configs.cfg sur votre instance de VM, définissez enabled = false sous [Snapshots], puis redémarrez l'agent invité :

    sudo systemctl restart google-guest-agent
    

Étape suivante