Configura copias de seguridad coherentes con la aplicación

En este documento, se muestra cómo configurar copias de seguridad programadas y coherentes con la aplicación, y flujos de trabajo de recuperación de un momento determinado (PITR) para bases de datos autoadministradas que se ejecutan en instancias de máquina virtual (VM) de Linux de Compute Engine.

Cuando creas copias de seguridad de cargas de trabajo de bases de datos con estado, como IBM Db2, SAP HANA, MySQL o PostgreSQL, las instantáneas estándar coherentes con fallas que toma Backup and DR pueden capturar la base de datos mientras las transacciones aún están en curso. Estas transacciones incompletas pueden dañar los datos, dejar las tablas en estados incoherentes y requerir rutinas de reparación de bases de datos extensas tras la recuperación de fallas. Las copias de seguridad coherentes con la aplicación resuelven estos problemas mediante la integración con el agente invitado de la VM para detener la base de datos y, de manera opcional, inmovilizar el sistema de archivos antes de crear una instantánea.

Antes de comenzar

Completa las siguientes tareas antes de configurar las copias de seguridad coherentes con la aplicación.

Roles obligatorios

Para obtener los permisos que necesitas para configurar las copias de seguridad coherentes con la aplicación, pídele a tu administrador que te otorgue los siguientes roles de IAM en tu proyecto:

Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.

También puedes obtener los permisos necesarios mediante roles personalizados o cualquier otro rol predefinido.

Requisitos previos

  1. En la Google Cloud consola, en la página del selector de proyectos, selecciona o crea un Google Cloud proyecto.

    Ir al selector de proyectos

  2. Verifica que la facturación esté habilitada para tu proyecto.

    Descubre cómo confirmar que tienes habilitada la facturación

  3. Habilita las APIs de Backup and DR y Secret Manager.

    Habilitar las API

  4. Asegúrate de que los datos de la base de datos y los archivos de registro estén almacenados en discos persistentes estándar Persistent Disks. Los volúmenes de Google Cloud Hyperdisk no admiten operaciones de limpieza de invitados.

  5. Si planeas configurar la recuperación de un momento determinado, configura tu base de datos para que archive sus registros de transacciones y rehaga los registros en un Persistent Disk dedicado y separado, por ejemplo, activado en /db2/ACT/log_archive.

Usa el framework de limpieza de invitados de tu propia secuencia de comandos (BYOS)

Backup and DR usa el framework de limpieza de invitados de tu propia secuencia de comandos (BYOS) para detener tu base de datos antes de que se tome una instantánea. El entorno invitado se basa en dos secuencias de comandos que residen en el directorio /etc/google/snapshots/ de tu instancia de VM de Linux:

  • Secuencia de comandos previa a la instantánea (/etc/google/snapshots/pre.sh): Se ejecuta antes de que se tome la instantánea. Esta secuencia de comandos debe detener las operaciones de la base de datos y, de manera opcional, puede inmovilizar el sistema de archivos.
  • Secuencia de comandos posterior a la instantánea (/etc/google/snapshots/post.sh): Se ejecuta después de que se toma la instantánea. Esta secuencia de comandos debe, de manera opcional, descongelar el sistema de archivos y reanudar las operaciones de la base de datos.

Para obtener más información sobre las plantillas de secuencias de comandos específicas de la base de datos, consulta Revisa las secuencias de comandos de muestra por tipo de base de datos.

Opcional: Inmoviliza y desinmoviliza los sistemas de archivos

La inmovilización del sistema de archivos con la utilidad estándar de Linux fsfreeze es opcional y no obligatoria. Detener la base de datos garantiza la coherencia de las transacciones a nivel de la aplicación. Sin embargo, si necesitas coherencia adicional a nivel del sistema de archivos, puedes incluir de manera opcional los siguientes comandos de inmovilización y desinmovilización del sistema de archivos en tus secuencias de comandos.

Asegúrate de que las secuencias de comandos pre.sh y post.sh de la VM estén configuradas para controlar la inmovilización opcional del sistema de archivos para los volúmenes de registro sin suspender las operaciones de la base de datos.

Agrega instrucciones de inmovilización del sistema de archivos a pre.sh

Si eliges inmovilizar los sistemas de archivos, agrega la siguiente lógica de descubrimiento e inmovilización al final de la secuencia de comandos pre.sh después de detener la base de datos:

# 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

Agrega instrucciones de desinmovilización del sistema de archivos a post.sh

Si inmovilizas los sistemas de archivos en pre.sh, agrega la siguiente lógica de desinmovilización al comienzo de la secuencia de comandos post.sh antes de reanudar la base de datos:

# 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

Recupera credenciales de forma dinámica con Secret Manager

Evita codificar de forma rígida las credenciales o contraseñas estáticas de la base de datos dentro de tus secuencias de comandos de shell. En su lugar, usa Secret Manager para recuperar credenciales de forma dinámica en el tiempo de ejecución. Reemplaza las variables de contraseña estáticas en tus secuencias de comandos con la siguiente lógica:

# 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

Reemplaza SECRET_NAME por el nombre del secreto en Secret Manager.

Revisa las secuencias de comandos de muestra por tipo de base de datos

En los siguientes ejemplos, se proporcionan implementaciones de pre.sh y post.sh para motores de bases de datos compatibles que se ejecutan en instancias de Linux.

IBM Db2

Secuencia de comandos previa a la instantánea (/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

Secuencia de comandos posterior a la instantánea (/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

Secuencia de comandos previa a la instantánea (/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

Secuencia de comandos posterior a la instantánea (/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

Secuencia de comandos previa a la instantánea (/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

Secuencia de comandos posterior a la instantánea (/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

Reemplaza lo siguiente:

  • DBSID: El identificador del sistema SAP HANA (SID) en mayúsculas.
  • DBADM: El usuario del SO administrador de SAP HANA (como <sid>adm).
  • HDB_KEY: La clave de userstore de SAP HANA configurada para el acceso a la base de datos.

SAP ASE

Secuencia de comandos previa a la instantánea (/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

Secuencia de comandos posterior a la instantánea (/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."

Reemplaza lo siguiente:

  • OS_USER: El usuario del sistema operativo que ejecuta SAP ASE (como sybase).
  • SYB_SERVER_NAME: El nombre del servidor de SAP ASE.
  • SYB_USER: El usuario de la base de datos con permisos para detener las bases de datos.
  • SYB_PASSWORD: La contraseña del usuario de la base de datos (o recupera de forma dinámica con Secret Manager).
  • DATABASE_LIST: Una lista separada por comas de las bases de datos que se detendrán.

SAP IQ

Secuencia de comandos previa a la instantánea (/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

Secuencia de comandos posterior a la instantánea (/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."

Reemplaza lo siguiente:

  • OS_USER: El usuario del sistema operativo que ejecuta SAP IQ (como sybiq).
  • DB_NAME: El nombre de la base de datos de SAP IQ.
  • DB_USER: El usuario de la base de datos con privilegios de DBA.
  • DB_PASSWORD: La contraseña del usuario de la base de datos (o recupera de forma dinámica con Secret Manager).
  • ENGINE_NAME: El nombre del motor de base de datos de SAP IQ.

SAP MaxDB

Secuencia de comandos previa a la instantánea (/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

Secuencia de comandos posterior a la instantánea (/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."

Reemplaza lo siguiente:

  • DBSID: El identificador del sistema SAP MaxDB (SID) en mayúsculas.
  • OS_USER: El usuario del sistema operativo que ejecuta MaxDB (como sdba).
  • DBM_USER: El usuario del administrador de la base de datos (DBM).
  • DBM_PASSWORD: La contraseña del usuario de DBM (o usa una clave de DBM almacenada: -k KEY_NAME).

PostgreSQL

Secuencia de comandos previa a la instantánea (/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

Secuencia de comandos posterior a la instantánea (/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."

Reemplaza lo siguiente:

  • OS_USER: El usuario del sistema operativo que ejecuta PostgreSQL (como postgres).
  • PG_HOME: La ruta de acceso al directorio de instalación de PostgreSQL.
  • DB_USER: El usuario de la base de datos de PostgreSQL con privilegios de superusuario.
  • PORT_NUMBER: El número de puerto en el que escucha PostgreSQL (predeterminado: 5432).
  • DB_NAME: El nombre de la base de datos a la que te conectarás.

MySQL

Secuencia de comandos previa a la instantánea (/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

Secuencia de comandos posterior a la instantánea (/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."

Reemplaza lo siguiente:

  • DB_USER: El usuario de la base de datos de MySQL con privilegios administrativos.
  • DB_PASSWORD: La contraseña de la base de datos de MySQL (o recupera de forma dinámica con Secret Manager).
  • PORT_NUMBER: El número de puerto en el que escucha MySQL (predeterminado: 3306).

MariaDB

Secuencia de comandos previa a la instantánea (/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

Secuencia de comandos posterior a la instantánea (/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

Reemplaza lo siguiente:

  • DB_USER: El usuario de la base de datos de MariaDB con privilegios administrativos.
  • DB_PASSWORD: La contraseña de la base de datos de MariaDB (o recupera de forma dinámica con Secret Manager).
  • PORT_NUMBER: El número de puerto en el que escucha MariaDB (predeterminado: 3306).

Implementa secuencias de comandos de limpieza de invitados

Después de preparar las secuencias de comandos pre.sh y post.sh para tu base de datos, impleméntalas en la instancia de VM de Linux:

  1. Conéctate a la instancia de VM de Linux que ejecuta tu base de datos autoadministrada con SSH.

  2. Crea el directorio /etc/google/snapshots/ si aún no existe:

    sudo mkdir -p /etc/google/snapshots
    
  3. Guarda tus secuencias de comandos pre.sh y post.sh personalizadas en el directorio /etc/google/snapshots/ de la instancia de VM.

  4. Asegúrate de que las secuencias de comandos tengan permisos de ejecución:

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

Habilita el agente de invitado para las instantáneas

Para permitir que Backup and DR ejecute secuencias de comandos previas y posteriores a la instantánea, habilita la integración de instantáneas en el entorno invitado de Compute Engine en tu instancia de VM de Linux:

  1. Conéctate a la instancia de VM de Linux que ejecuta tu base de datos autoadministrada con SSH (si aún no está conectada).

  2. Abre el archivo de configuración del entorno invitado en un editor de texto:

    sudo nano /etc/default/instance_configs.cfg
    
  3. Agrega o modifica la siguiente configuración en la sección [Snapshots] para habilitar las instantáneas:

    [Snapshots]
    enabled = true
    timeout_in_seconds = 120
    
  4. Reinicia el agente invitado en la instancia de VM para aplicar los cambios:

    sudo systemctl restart google-guest-agent
    

Configura el plan de copia de seguridad

Ahora que la instancia de VM está configurada con las secuencias de comandos de limpieza de invitados y el agente invitado está habilitado para las instantáneas, configura un plan de copia de seguridad en la Google Cloud consola:

  1. En la Google Cloud consola de, ve a la página Backup and DR.

    Ir a Backup and DR

  2. En el menú de navegación, selecciona Planes de copia de seguridad.

  3. Haz clic en Crear plan de copia de seguridad o selecciona un plan de copia de seguridad existente y haz clic en Editar.

  4. En los pasos de configuración de Copia de seguridad de instancias, busca las opciones de coherencia.

  5. Selecciona la opción Habilitar coherencia de la aplicación.

  6. Guarda y aplica el plan de copia de seguridad a tu instancia de VM. Según la programación, el plan de copia de seguridad activa el agente invitado para ejecutar la secuencia de comandos pre.sh, tomar la instantánea y ejecutar la secuencia de comandos post.sh.

Configura la copia de seguridad de Persistent Disk para la recuperación de un momento determinado de la base de datos

Para las bases de datos autoadministradas, como Db2 y SAP HANA, puedes configurar copias de seguridad independientes de Persistent Disk para capturar registros de archivo de la base de datos, lo que permite la recuperación de un momento determinado. Si no necesitas la recuperación de un momento determinado, puedes omitir la sección Inhabilita las secuencias de comandos de limpieza de invitados.

Prácticas recomendadas para las copias de seguridad de registros de recuperación de un momento determinado

  • Frecuencia: Configura la programación del plan de copia de seguridad para que este disco de registro dedicado sea igual a la granularidad del registro de recuperación de un momento determinado, por ejemplo, cada 15 minutos o por hora.

  • Optimización de costos: Almacenar instantáneas frecuentes puede aumentar los costos de almacenamiento. Para minimizar la sobrecarga, configura el período de retención mínimo y el período de vault de inmutabilidad correspondiente al tiempo mínimo permitido que aún satisfaga tu ventana de recuperación de un momento determinado.

Recupera una base de datos autoadministrada a un momento específico

Si configuraste copias de seguridad de VM periódicas junto con copias de seguridad de registros de Persistent Disk dedicadas, sigue este procedimiento para restablecer tu base de datos a un momento específico. Si no configuraste copias de seguridad de registros dedicadas o no necesitas la recuperación de un momento determinado, consulta Restablece una instancia de Compute Engine desde una backup vault para restablecer tu VM directamente y omite la sección Realiza tareas posteriores al restablecimiento.

Flujo de trabajo de recuperación

  1. Restablece la VM base: Selecciona la copia de seguridad de la instancia (imagen de máquina) de la vault de copia de seguridad que precede a tu hora de recuperación de destino. Restablécela siguiendo los procedimientos de restablecimiento estándar de Compute Engine. Para obtener instrucciones, consulta Restablece una instancia de Compute Engine desde una vault de copia de seguridad.

    Si no configuraste copias de seguridad de registros dedicadas o no necesitas la recuperación de un momento determinado, omite el paso 4.

  2. Conecta los discos de registro: Identifica y restablece las instantáneas de disco de registro pertinentes capturadas hasta tu hora de recuperación de destino. Conecta estos discos recién creados a la instancia restablecida.

  3. Avanza la base de datos: Conéctate a la instancia restablecida con SSH y ejecuta el comando de avance específico de la base de datos, como ROLLFORWARD DATABASE en Db2, con los registros ubicados en los discos persistentes recién conectados.

  4. Realiza tareas posteriores al restablecimiento: Realiza los pasos específicos de la base de datos necesarios para poner en línea la aplicación.

Inhabilita las secuencias de comandos de limpieza de invitados

Para quitar las secuencias de comandos de limpieza de invitados personalizadas y, luego, inhabilitar la coherencia de la aplicación, haz lo siguiente:

  1. Anula la asignación del plan de copia de seguridad de tu instancia: En la Google Cloud consola, ve a la página Backup and DR, busca tu instancia de VM en Recursos protegidos y anula la asignación o borra la asociación del plan de copia de seguridad.

  2. Quita las secuencias de comandos de limpieza de invitados: Conéctate a tu instancia de VM de Linux con SSH y quita las secuencias de comandos de limpieza de invitados personalizadas:

    sudo rm -f /etc/google/snapshots/pre.sh /etc/google/snapshots/post.sh
    
  3. Inhabilita la integración de instantáneas en el agente invitado: Abre /etc/default/instance_configs.cfg en tu instancia de VM, establece enabled = false en [Snapshots] y reinicia el agente invitado:

    sudo systemctl restart google-guest-agent
    

¿Qué sigue?