애플리케이션 일관성 백업 구성

이 문서에서는 Compute Engine Linux 가상 머신 (VM) 인스턴스에서 실행되는 자체 관리 데이터베이스의 예약된 애플리케이션 일관성 백업 및 특정 시점 복구 (PITR) 워크플로를 구성하는 방법을 보여줍니다.

IBM Db2, SAP HANA, MySQL 또는 PostgreSQL과 같은 상태 저장 데이터베이스 워크로드를 백업할 때 백업 및 DR에서 가져온 표준 비일관성 스냅샷은 트랜잭션이 아직 진행 중인 동안 데이터베이스를 캡처할 수 있습니다. 이러한 불완전한 트랜잭션은 데이터를 손상시키고 테이블을 일관되지 않은 상태로 두며 비정상 종료 복구 시 긴 데이터베이스 복구 루틴이 필요할 수 있습니다. 애플리케이션 일관성 백업은 스냅샷을 만들기 전에 VM 게스트 에이전트와 통합하여 데이터베이스를 정지하고 선택적으로 파일 시스템을 고정함으로써 이러한 문제를 해결합니다.

시작하기 전에

애플리케이션 일관성 백업을 구성하기 전에 다음 작업을 완료합니다.

필요한 역할

애플리케이션 일관성 백업을 구성하는 데 필요한 권한을 얻으려면 관리자에게 프로젝트에 대한 다음 IAM 역할을 부여해 달라고 요청하세요.

역할 부여에 대한 자세한 내용은 프로젝트, 폴더, 조직에 대한 액세스 관리를 참조하세요.

커스텀 역할이나 다른 사전 정의된 역할을 통해 필요한 권한을 얻을 수도 있습니다.

기본 요건

  1. Google Cloud 콘솔의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.

    프로젝트 선택기로 이동

  2. 프로젝트에 결제가 사용 설정되어 있는지 확인합니다.

    결제가 사용 설정되어 있는지 확인하는 방법 알아보기

  3. 백업 및 DR 및 Secret Manager API를 사용 설정합니다.

    API 사용 설정

  4. 데이터베이스 데이터 및 로그 파일이 표준 영구 디스크에 저장되어 있는지 확인합니다. Google Cloud Hyperdisk 볼륨은 게스트 삭제 작업을 지원하지 않습니다.

  5. PITR(point-in-time recovery)을 구성하려면 트랜잭션 및 재실행 로그를 전용의 별도 Persistent Disk(예: /db2/ACT/log_archive에 마운트됨)에 보관하도록 데이터베이스를 구성합니다.

Bring-Your-Own-Script (BYOS) 게스트 삭제 프레임워크 사용

백업 및 DR은 Bring-Your-Own-Script (BYOS) 게스트 삭제 프레임워크를 사용하여 스냅샷을 가져오기 전에 데이터베이스를 정지합니다. 게스트 환경은 Linux VM 인스턴스의 /etc/google/snapshots/ 디렉터리에 있는 두 개의 스크립트를 사용합니다.

  • 사전 스냅샷 스크립트 (/etc/google/snapshots/pre.sh): 스냅샷을 가져오기 전에 실행됩니다. 이 스크립트는 데이터베이스 작업을 정지해야 하며 선택적으로 파일 시스템을 고정할 수 있습니다.
  • 사후 스냅샷 스크립트 (/etc/google/snapshots/post.sh): 스냅샷을 가져온 후에 실행됩니다. 이 스크립트는 선택적으로 파일 시스템을 고정 해제하고 데이터베이스 작업을 재개해야 합니다.

데이터베이스별 스크립트 템플릿에 대한 자세한 내용은 데이터베이스 유형별 샘플 스크립트 검토를 참조하세요.

(선택사항) 파일 시스템 고정 및 고정 해제

표준 Linux 유틸리티 fsfreeze를 사용하여 파일 시스템을 고정하는 것은 선택사항이며 필수는 아닙니다. 데이터베이스를 정지하면 애플리케이션 수준 트랜잭션 일관성이 보장됩니다. 하지만 파일 시스템 수준 일관성이 추가로 필요한 경우 스크립트에 다음 파일 시스템 고정 및 고정 해제 명령어를 선택적으로 포함할 수 있습니다.

VM의 pre.shpost.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의 보안 비밀 이름으로 바꿉니다.

데이터베이스 유형별 샘플 스크립트 검토

다음 샘플은 Linux 인스턴스에서 실행되는 지원되는 데이터베이스 엔진의 pre.shpost.sh 구현을 제공합니다.

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: 대문자로 된 SAP HANA 시스템 식별자 (SID)입니다.
  • DBADM: SAP HANA 관리자 OS 사용자 (예: <sid>adm)입니다.
  • HDB_KEY: 데이터베이스 액세스를 위해 구성된 SAP HANA 사용자 저장소 키입니다.

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: 대문자로 된 SAP MaxDB 시스템 식별자 (SID)입니다.
  • 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).

게스트 삭제 스크립트 배포

데이터베이스의 pre.shpost.sh 스크립트를 준비한 후 Linux VM 인스턴스에 배포합니다.

  1. SSH를 사용하여 자체 관리 데이터베이스를 실행하는 Linux VM 인스턴스에 연결합니다.

  2. /etc/google/snapshots/ 디렉터리가 아직 없는 경우 만듭니다.

    sudo mkdir -p /etc/google/snapshots
    
  3. 커스텀 pre.shpost.sh 스크립트를 VM 인스턴스의 /etc/google/snapshots/ 디렉터리에 저장합니다.

  4. 스크립트에 실행 권한이 있는지 확인합니다.

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

스냅샷의 게스트 에이전트 사용 설정

백업 및 DR에서 사전 스냅샷 및 사후 스냅샷 스크립트를 실행하도록 허용하려면 Linux VM 인스턴스의 Compute Engine 게스트 환경에서 스냅샷 통합을 사용 설정합니다.

  1. SSH를 사용하여 자체 관리 데이터베이스를 실행하는 Linux VM 인스턴스에 연결합니다 (아직 연결되지 않은 경우).

  2. 텍스트 편집기에서 게스트 환경 구성 파일을 엽니다.

    sudo nano /etc/default/instance_configs.cfg
    
  3. [Snapshots] 섹션에서 다음 설정을 추가하거나 수정하여 스냅샷을 사용 설정합니다.

    [Snapshots]
    enabled = true
    timeout_in_seconds = 120
    
  4. VM 인스턴스에서 게스트 에이전트를 다시 시작하여 변경사항을 적용합니다.

    sudo systemctl restart google-guest-agent
    

백업 계획 구성

이제 VM 인스턴스가 게스트 삭제 스크립트로 구성되고 스냅샷에 게스트 에이전트 가 사용 설정되었으므로 Google Cloud 콘솔에서 백업 계획을 구성합니다.

  1. Google Cloud 콘솔에서 백업 및 DR 페이지로 이동합니다.

    백업 및 DR로 이동

  2. 탐색 메뉴에서 백업 계획 을 선택합니다.

  3. 백업 계획 만들기 를 클릭하거나 기존 백업 계획을 선택하고 수정을 클릭합니다.

  4. 인스턴스 백업 구성 단계에서 일관성 옵션을 찾습니다.

  5. 애플리케이션 일관성 사용 설정 옵션을 선택합니다.

  6. 백업 계획을 VM 인스턴스에 저장하고 적용합니다. 일정에 따라 백업 계획은 게스트 에이전트를 트리거하여 pre.sh 스크립트를 실행하고 스냅샷을 가져오고 post.sh 스크립트를 실행합니다.

데이터베이스 PITR(point-in-time recovery)을 위한 영구 디스크 백업 구성

Db2 및 SAP HANA와 같은 자체 관리 데이터베이스의 경우 독립형 Persistent Disk 백업을 구성하여 데이터베이스 보관 로그를 캡처하고 PITR(point-in-time recovery)을 사용 설정할 수 있습니다. PITR(특정 시점 복구)이 필요하지 않은 경우 게스트 플러시 스크립트 사용 중지로 건너뜁니다.

PITR(point-in-time recovery) 로그 백업 권장사항

  • 빈도: 이 전용 로그 디스크의 백업 계획 일정을 PITR(point-in-time recovery) 로그 세분성과 동일하게 구성합니다(예: 15분마다 또는 매시간).

  • 비용 최적화: 스냅샷을 자주 저장하면 스토리지 비용이 증가할 수 있습니다. 오버헤드를 최소화하려면 특정 시점 복구 기간을 여전히 충족하는 최소 허용 시간으로 최소 보관 기간 및 해당 변경 불가능한 Vault 기간 을 구성합니다.

자체 관리 데이터베이스를 특정 시점으로 복구

전용 영구 디스크 로그 백업과 함께 정기 VM 백업을 구성한 경우 이 절차에 따라 데이터베이스를 특정 시점으로 복원합니다. 전용 로그 백업을 구성하지 않았거나 특정 시점 복구가 필요하지 않은 경우 백업 Vault에서 Compute Engine 인스턴스 복원을 참조하여 VM을 직접 복원하고 복원 후 작업 수행으로 건너뜁니다.

복구 워크플로

  1. 기본 VM 복원: 대상 복구 시간 이전의 백업 Vault에서 인스턴스 백업 (머신 이미지) 을 선택합니다. 표준 Compute Engine 복원 절차에 따라 복원합니다. 자세한 내용은 Backup Vault에서 Compute Engine 인스턴스 복원을 참조하세요.

    전용 로그 백업을 구성하지 않았거나 PITR(point-in-time recovery)이 필요하지 않은 경우 4단계로 건너뜁니다.

  2. 로그 디스크 연결: 대상 복구 시간까지 캡처된 관련 로그 디스크 스냅샷 을 식별하고 복원합니다. 새로 만든 디스크를 복원된 인스턴스에 연결합니다.

  3. 데이터베이스 롤포워드: SSH를 사용하여 복원된 인스턴스에 연결하고 새로 연결된 영구 디스크에 있는 로그를 사용하여 데이터베이스별 롤포워드 명령어(예: Db2의 ROLLFORWARD DATABASE)를 실행합니다.

  4. 복원 후 작업 수행: 애플리케이션을 온라인으로 전환하는 데 필요한 데이터베이스별 단계를 수행합니다.

게스트 삭제 스크립트 사용 중지

커스텀 게스트 삭제 스크립트를 삭제하고 애플리케이션 일관성을 사용 중지하려면 다음 단계를 따르세요.

  1. 인스턴스에서 백업 계획 할당 해제: 콘솔 Google Cloud 에서 백업 및 DR 페이지로 이동하고 보호된 리소스에서 VM 인스턴스를 찾은 후 백업 계획 연결을 할당 해제하거나 삭제합니다.

  2. 게스트 삭제 스크립트 삭제: SSH를 사용하여 Linux VM 인스턴스에 연결하고 커스텀 게스트 삭제 스크립트를 삭제합니다.

    sudo rm -f /etc/google/snapshots/pre.sh /etc/google/snapshots/post.sh
    
  3. 게스트 에이전트에서 스냅샷 통합 사용 중지: VM 인스턴스에서 /etc/default/instance_configs.cfg를 열고 enabled = false에서 [Snapshots]를 설정한 후 게스트 에이전트를 다시 시작합니다.

    sudo systemctl restart google-guest-agent
    

다음 단계