이 문서에서는 Compute Engine Linux 가상 머신 (VM) 인스턴스에서 실행되는 자체 관리 데이터베이스의 예약된 애플리케이션 일관성 백업 및 특정 시점 복구 (PITR) 워크플로를 구성하는 방법을 보여줍니다.
IBM Db2, SAP HANA, MySQL 또는 PostgreSQL과 같은 상태 저장 데이터베이스 워크로드를 백업할 때 백업 및 DR에서 가져온 표준 비일관성 스냅샷은 트랜잭션이 아직 진행 중인 동안 데이터베이스를 캡처할 수 있습니다. 이러한 불완전한 트랜잭션은 데이터를 손상시키고 테이블을 일관되지 않은 상태로 두며 비정상 종료 복구 시 긴 데이터베이스 복구 루틴이 필요할 수 있습니다. 애플리케이션 일관성 백업은 스냅샷을 만들기 전에 VM 게스트 에이전트와 통합하여 데이터베이스를 정지하고 선택적으로 파일 시스템을 고정함으로써 이러한 문제를 해결합니다.
시작하기 전에
애플리케이션 일관성 백업을 구성하기 전에 다음 작업을 완료합니다.
필요한 역할
애플리케이션 일관성 백업을 구성하는 데 필요한 권한을 얻으려면 관리자에게 프로젝트에 대한 다음 IAM 역할을 부여해 달라고 요청하세요.
-
백업 계획을 구성하고 관리하려면:
백업 및 DR 백업 사용자 (
roles/backupdr.backupUser) -
Compute Engine 인스턴스를 관리하려면:
Compute 인스턴스 관리자 (v1) (
roles/compute.instanceAdmin.v1) -
스크립트에서 Secret Manager 보안 비밀에 액세스하려면:
Secret Manager 보안 비밀 접근자 (
roles/secretmanager.secretAccessor)
역할 부여에 대한 자세한 내용은 프로젝트, 폴더, 조직에 대한 액세스 관리를 참조하세요.
커스텀 역할이나 다른 사전 정의된 역할을 통해 필요한 권한을 얻을 수도 있습니다.
기본 요건
Google Cloud 콘솔의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.
프로젝트에 결제가 사용 설정되어 있는지 확인합니다.
백업 및 DR 및 Secret Manager API를 사용 설정합니다.
데이터베이스 데이터 및 로그 파일이 표준 영구 디스크에 저장되어 있는지 확인합니다. Google Cloud Hyperdisk 볼륨은 게스트 삭제 작업을 지원하지 않습니다.
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.sh 및 post.sh 스크립트가 데이터베이스 작업을 일시중지하지 않고 로그 볼륨의 선택적 파일 시스템 고정을 처리하도록 구성되어 있는지 확인합니다.
pre.sh에 파일 시스템 고정 안내 추가
파일 시스템을 고정하도록 선택한 경우 데이터베이스를 정지한 후 pre.sh 스크립트 끝에 다음 검색 및 고정 로직을 추가합니다.
# Discover local writeable mount points
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
# FREEZE FILESYSTEMS (Optional)
for mnt in $MOUNT_POINTS; do
if ! sudo fsfreeze -f "$mnt"; then
logger "Error: Failed to freeze $mnt. Cleaning up..."
# Attempt emergency thaw
for thaw_mnt in $MOUNT_POINTS; do sudo fsfreeze -u "$thaw_mnt" 2>/dev/null; done
# Add your database-specific resume/cleanup commands here before exiting
exit 1
fi
logger "Filesystem $mnt is frozen."
done
post.sh에 파일 시스템 고정 해제 안내 추가
pre.sh에서 파일 시스템을 고정하는 경우 데이터베이스를 재개하기 전에 post.sh 스크립트 시작 부분에 다음 고정 해제 로직을 추가합니다.
# Discover local writeable mount points
MOUNT_POINTS=$(findmnt -n -l -o TARGET -t xfs,ext4,ext3,ext2,btrfs)
# UNFREEZE FILESYSTEMS (Optional)
for mnt in $MOUNT_POINTS; do
sudo fsfreeze -u "$mnt"
logger "Filesystem $mnt is unfrozen."
done
Secret Manager로 사용자 인증 정보 동적으로 가져오기
셸 스크립트 내부에 정적 데이터베이스 사용자 인증 정보 또는 비밀번호를 하드 코딩하지 마세요. 대신 Secret Manager를 사용하여 런타임에 사용자 인증 정보를 동적으로 가져옵니다. 스크립트의 정적 비밀번호 변수를 다음 로직으로 바꿉니다.
# Fetch the database password from Secret Manager dynamically
DBPASSWORD=$(gcloud secrets versions access latest \
--secret="SECRET_NAME" \
--format='get(payload.data)' | tr -d '\n')
if [ $? -ne 0 ]; then
logger "Critical Error: Unable to fetch the password from Secret Manager."
exit 1
fi
SECRET_NAME을 Secret Manager의 보안 비밀 이름으로 바꿉니다.
데이터베이스 유형별 샘플 스크립트 검토
다음 샘플은 Linux 인스턴스에서 실행되는 지원되는 데이터베이스 엔진의 pre.sh 및 post.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.sh 및 post.sh 스크립트를 준비한 후 Linux VM 인스턴스에 배포합니다.
SSH를 사용하여 자체 관리 데이터베이스를 실행하는 Linux VM 인스턴스에 연결합니다.
/etc/google/snapshots/디렉터리가 아직 없는 경우 만듭니다.sudo mkdir -p /etc/google/snapshots커스텀
pre.sh및post.sh스크립트를 VM 인스턴스의/etc/google/snapshots/디렉터리에 저장합니다.스크립트에 실행 권한이 있는지 확인합니다.
sudo chmod 755 /etc/google/snapshots/pre.sh /etc/google/snapshots/post.sh
스냅샷의 게스트 에이전트 사용 설정
백업 및 DR에서 사전 스냅샷 및 사후 스냅샷 스크립트를 실행하도록 허용하려면 Linux VM 인스턴스의 Compute Engine 게스트 환경에서 스냅샷 통합을 사용 설정합니다.
SSH를 사용하여 자체 관리 데이터베이스를 실행하는 Linux VM 인스턴스에 연결합니다 (아직 연결되지 않은 경우).
텍스트 편집기에서 게스트 환경 구성 파일을 엽니다.
sudo nano /etc/default/instance_configs.cfg[Snapshots]섹션에서 다음 설정을 추가하거나 수정하여 스냅샷을 사용 설정합니다.[Snapshots] enabled = true timeout_in_seconds = 120VM 인스턴스에서 게스트 에이전트를 다시 시작하여 변경사항을 적용합니다.
sudo systemctl restart google-guest-agent
백업 계획 구성
이제 VM 인스턴스가 게스트 삭제 스크립트로 구성되고 스냅샷에 게스트 에이전트 가 사용 설정되었으므로 Google Cloud 콘솔에서 백업 계획을 구성합니다.
Google Cloud 콘솔에서 백업 및 DR 페이지로 이동합니다.
탐색 메뉴에서 백업 계획 을 선택합니다.
백업 계획 만들기 를 클릭하거나 기존 백업 계획을 선택하고 수정을 클릭합니다.
인스턴스 백업 구성 단계에서 일관성 옵션을 찾습니다.
애플리케이션 일관성 사용 설정 옵션을 선택합니다.
백업 계획을 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을 직접 복원하고 복원 후 작업 수행으로 건너뜁니다.
복구 워크플로
기본 VM 복원: 대상 복구 시간 이전의 백업 Vault에서 인스턴스 백업 (머신 이미지) 을 선택합니다. 표준 Compute Engine 복원 절차에 따라 복원합니다. 자세한 내용은 Backup Vault에서 Compute Engine 인스턴스 복원을 참조하세요.
전용 로그 백업을 구성하지 않았거나 PITR(point-in-time recovery)이 필요하지 않은 경우 4단계로 건너뜁니다.
로그 디스크 연결: 대상 복구 시간까지 캡처된 관련 로그 디스크 스냅샷 을 식별하고 복원합니다. 새로 만든 디스크를 복원된 인스턴스에 연결합니다.
데이터베이스 롤포워드: SSH를 사용하여 복원된 인스턴스에 연결하고 새로 연결된 영구 디스크에 있는 로그를 사용하여 데이터베이스별 롤포워드 명령어(예: Db2의
ROLLFORWARD DATABASE)를 실행합니다.복원 후 작업 수행: 애플리케이션을 온라인으로 전환하는 데 필요한 데이터베이스별 단계를 수행합니다.
게스트 삭제 스크립트 사용 중지
커스텀 게스트 삭제 스크립트를 삭제하고 애플리케이션 일관성을 사용 중지하려면 다음 단계를 따르세요.
인스턴스에서 백업 계획 할당 해제: 콘솔 Google Cloud 에서 백업 및 DR 페이지로 이동하고 보호된 리소스에서 VM 인스턴스를 찾은 후 백업 계획 연결을 할당 해제하거나 삭제합니다.
게스트 삭제 스크립트 삭제: SSH를 사용하여 Linux VM 인스턴스에 연결하고 커스텀 게스트 삭제 스크립트를 삭제합니다.
sudo rm -f /etc/google/snapshots/pre.sh /etc/google/snapshots/post.sh게스트 에이전트에서 스냅샷 통합 사용 중지: VM 인스턴스에서
/etc/default/instance_configs.cfg를 열고enabled = false에서[Snapshots]를 설정한 후 게스트 에이전트를 다시 시작합니다.sudo systemctl restart google-guest-agent