Se i file di database SQL Server sono distribuiti su più dischi, puoi eseguire il backup di tutti i dischi contemporaneamente, mantenendo la coerenza di applicazioni e dati. Puoi ottenere questo backup point-in-time esatto con i gruppi di coerenza di snapshot istantanei di Compute Engine, che ti consentono di eseguire il backup dei dati su un gruppo di dischi.
Questo tutorial descrive come eseguire il backup dei database SQL Server con gli snapshot di Compute Engine e la funzionalità di snapshot Transact-SQL (T-SQL) disponibile in SQL Server 2022 e versioni successive. Questa soluzione supporta i deployment Windows e Linux e riduce al minimo l'impatto sulle prestazioni dei workload live.
Come funziona
Il flusso di lavoro è costituito da questi passaggi principali, gestiti da uno script in esecuzione su un'istanza di Compute:
- Blocca il database: lo script invia un comando T-SQL a SQL Server per sospendere tutte le operazioni di scrittura per i database di destinazione. In questo modo, i file di database si trovano in uno stato coerente per il backup.
- Acquisisci snapshot istantanei: mentre il database è bloccato, crea un gruppo di snapshot istantanei di i dischi in cui risiedono i file di dati e di log del database. Questo è l' Google Cloud equivalente dell'utilizzo di un meccanismo di snapshot a livello di hardware o di servizio.
- Registra e sblocca: lo script invia un altro comando T-SQL a SQL Server per registrare i
metadati di backup. Questo comando crea un piccolo file di backup che rimanda al gruppo di coerenza
degli snapshot istantanei e viene registrato nella cronologia dei backup
msdb. Al termine, SQL Server sblocca automaticamente il database e riprende le normali operazioni.
In genere, l'intero processo viene completato in meno di un secondo, riducendo al minimo la durata del blocco di scrittura sul database. Durante il blocco, i dati possono essere letti, ma non scritti. Puoi annullare manualmente lo stato di blocco impostando SUSPEND_FOR_SNAPSHOT_BACKUP=OFF per il database.
Obiettivi
In questo tutorial imparerai a completare le seguenti attività:- Crea un'istanza SQL Server con due dischi dati.
- Crea un nuovo database con i file di dati e di log su dischi separati.
- Crea un gruppo di coerenza di tutti i dischi della VM che esegue SQL Server.
- Crea snapshot istantanei del gruppo di dischi.
- Crea nuovi dischi dagli snapshot istantanei.
Costi
In questo documento vengono utilizzati i seguenti componenti fatturabili di Google Cloud:
Per generare una stima dei costi in base all'utilizzo previsto,
utilizza il calcolatore prezzi.
Al termine delle attività descritte in questo documento, puoi evitare l'addebito di ulteriori costi eliminando le risorse che hai creato. Per saperne di più, consulta Esegui la pulizia.
Prima di iniziare
Per questo tutorial, è necessario un Google Cloud progetto. Puoi crearne uno nuovo o selezionarne uno esistente:
-
Nella Google Cloud console, nella pagina di selezione del progetto, seleziona o crea un Google Cloud progetto.
Ruoli necessari per selezionare o creare un progetto
- Seleziona un progetto: la selezione di un progetto non richiede un ruolo IAM specifico. Puoi selezionare qualsiasi progetto su cui ti è stato concesso un ruolo.
-
Crea un progetto: per creare un progetto, devi disporre del ruolo Autore progetto
(
roles/resourcemanager.projectCreator), che contiene l'resourcemanager.projects.createautorizzazione. Scopri come concedere i ruoli.
-
Verifica che la fatturazione sia attivata per il tuo Google Cloud progetto.
-
Nella Google Cloud console, attiva Cloud Shell.
-
Assicurati che Microsoft SQL Server 2022 o versioni successive sia installato e in esecuzione.
Autorizzazioni obbligatorie
Oltre all'accesso in lettura standard, assicurati che l'amministratore di SQL Server ti conceda l'autorizzazione ALTER DATABASE per il database di destinazione.
Per ottenere le autorizzazioni necessarie per creare un'istanza e creare snapshot, chiedi all'amministratore di concederti i seguenti ruoli IAM nel progetto:
-
Gestisci istanza:
compute.instanceAdmin.v1 -
Crea snapshot:
compute.storageAdmin
Per saperne di più sulla concessione dei ruoli, consulta Gestisci l'accesso a progetti, cartelle e organizzazioni.
Potresti anche riuscire a ottenere le autorizzazioni richieste tramite i ruoli personalizzati o altri ruoli predefiniti.
Crea un'istanza SQL di Compute Engine
Crea un'istanza SQL Server.
Nella console Google Cloud , apri Cloud Shell facendo clic sul pulsante Attiva Cloud Shell
.
Crea un'istanza SQL Server. Incolla il seguente comando:
REGION=REGIONZONE=$REGION-a VM_NAME=VM_NAMEgcloud compute instances create $VM_NAME \ --boot-disk-auto-delete \ --boot-disk-size 100 \ --boot-disk-type hyperdisk-balanced \ --image-family sql-std-2022-win-2025 \ --image-project windows-sql-cloud \ --machine-type c4-highmem-4 \ --zone $ZONE \ --network-interface subnet=default \ --tags sql-server-instant-snapshot \ --scopes=cloud-platform,service-control,service-management,monitoring-write,logging-write,storage-rw \ --create-disk=device-name=$VM_NAME-data-disk1,mode=rw,name=$VM_NAME-data-disk1,size=100,type=hyperdisk-balanced \ --create-disk=device-name=$VM_NAME-data-disk2,mode=rw,name=$VM_NAME-data-disk2,size=100,type=hyperdisk-balanced
Sostituisci quanto segue:
- Regione: la regione in cui verrà eseguito il deployment della nuova istanza.
- VM_NAME: il nome della nuova istanza SQL Server.
Crea un gruppo di coerenza dei dischi
Crea un gruppo di coerenza.
gcloud compute resource-policies create disk-consistency-group $VM_NAME-snap-grp \ --region=$REGIONAggiungi i dischi della VM al gruppo di coerenza.
gcloud compute disks add-resource-policies $VM_NAME \ --zone=$ZONE \ --resource-policies=$VM_NAME-snap-grp gcloud compute disks add-resource-policies $VM_NAME-data-disk1 \ --zone=$ZONE \ --resource-policies=$VM_NAME-snap-grp gcloud compute disks add-resource-policies $VM_NAME-data-disk2 \ --zone=$ZONE \ --resource-policies=$VM_NAME-snap-grp
Crea un nuovo database
- Crea un nome utente e una password per l'istanza VM.
- Connettiti alla VM utilizzando Remote Desktop e accedi con il nome utente e la password creati nel passaggio precedente.
- Fai clic con il tasto destro del mouse sul pulsante Start (o premi Win+X) e poi fai clic su Terminale (Amministratore).
- Conferma la richiesta di elevazione facendo clic su Sì.
Esegui il seguente script PowerShell nella finestra del terminale aperta. Questo script inizializza il disco dati, lo formatta con una dimensione del blocco di 64 KB e assegna una lettera di unità.
$availableDisks = Get-PhysicalDisk -CanPool $True $diskLetters = [char[]] (68..72) | Where-Object { !(Get-PSDrive $_ -ErrorAction SilentlyContinue) } $diskCount = 0 foreach ($disk in $availableDisks) { $diskLetter = $diskLetters[$diskCount] $diskLabel = "$diskLetter-DataDisk" Initialize-Disk -Number $disk.DeviceId -PartitionStyle MBR -PassThru New-Partition -DiskNumber $disk.DeviceId -UseMaximumSize ` -DriveLetter $diskLetter | Format-Volume -FileSystem NTFS ` -NewFileSystemLabel $diskLabel -AllocationUnitSize 65536 -Confirm:$false New-Item -ItemType Directory -Path "$($diskLetter):\MSSQL" $diskCount = $diskCount +1 }Apri SQL Server Management Studio (SSMS). Eseguilo come amministratore.
Nella finestra di dialogo Connettiti al server, verifica che il nome del server sia impostato su
localhoste seleziona Connetti.Nel menu File, seleziona File > Nuovo > Query con la connessione attuale.
Copia il seguente codice nella finestra di query appena aperta.
USE Master; GO CREATE DATABASE SnapBackupDB ON PRIMARY ( NAME = 'SnapBackupDB_Data', FILENAME = 'D:\MSSQL\SnapBackupDB.mdf', SIZE = 500MB, MAXSIZE = UNLIMITED, FILEGROWTH = 64MB ) LOG ON ( NAME = 'SnapBackupDB_Log', FILENAME = 'E:\MSSQL\SnapBackupDB_log.ldf', SIZE = 250MB, MAXSIZE = 2GB, FILEGROWTH = 64MB );
Esegui il deployment dello script di snapshot
Questo script automatizza l'intero processo necessario per acquisire snapshot coerenti con l'applicazione dei dischi collegati alla VM che esegue SQL Server.
- Utilizzando la stessa sessione di Remote Desktop, apri Blocco note.
- Copia i contenuti dello script seguente e incollali nella finestra del Blocco note aperta.
Salva il file come
take-snapshot.ps1inc:\scripts# Import Modules Import-Module -Name SQLPS # Set variables $formattedTimestamp = Get-Date -Format 'yyyyMMdd-HHmmss' $backupLocation = 'D:\MSSQL\Backup' $dbName = 'SnapBackupDB' $bkmFile = Join-Path -Path $backupLocation -ChildPath ("${dbName}_${formattedTimestamp}.bkm") $sqlServer = 'localhost' # SQL Commands $suspendDbCmd = "ALTER DATABASE [$dbName] SET SUSPEND_FOR_SNAPSHOT_BACKUP=ON WITH NO_WAIT;" $backupMetadataCmd = "BACKUP DATABASE [$dbName] TO DISK='$bkmFile' WITH METADATA_ONLY, FORMAT;" $unsuspendDbCmd = "ALTER DATABASE [$dbName] SET SUSPEND_FOR_SNAPSHOT_BACKUP=OFF;" # --- Helper Function for SQL Execution --- function Invoke-MySqlCommand { param( [Parameter(Mandatory=$true)] [string]$CommandText, [Parameter(Mandatory=$true)] [System.Data.SqlClient.SqlConnection]$SqlConnection ) Write-Host "Executing SQL Command: $($CommandText)" try { $Command = New-Object System.Data.SqlClient.SqlCommand($CommandText, $SqlConnection) $Result = $Command.ExecuteNonQuery() return $true } catch { Write-Host "Error executing SQL Command: $($CommandText)`n$($_.Exception.Message)" -ForegroundColor Red return $false } } $sqlConn = New-Object System.Data.SqlClient.SqlConnection $sqlConn.ConnectionString = "server='$sqlServer';database='$dbName';Integrated Security=True;" $databaseSuspended = $false if (-not(Test-Path $backupLocation)) { New-Item -Path $backupLocation -ItemType directory -Force } try { $instanceName = (Invoke-RestMethod -Headers @{"Metadata-Flavor"="Google"} -Uri "http://metadata.google.internal/computeMetadata/v1/instance/name") $vmConfigString = (gcloud compute instances list --filter="name=('$instanceName')" --format=json --quiet) if ($LASTEXITCODE -ne 0) { Write-Host "Error querying gcloud for VM instances (exit code: $LASTEXITCODE). Exiting." -ForegroundColor Red exit 1 } $vmConfig = $vmConfigString | ConvertFrom-Json # Open SQL Server connection $sqlConn.Open() # Suspend Database Write-Host "Suspending database '$dbName' for snapshot..." if (-not (Invoke-MySqlCommand -CommandText $suspendDbCmd -SqlConnection $sqlConn)) { Write-Host "Failed to suspend database. Exiting." -ForegroundColor Red exit 1 } $databaseSuspended = $true # Take a disk snapshot try { $consistencyGroupListStr = (gcloud compute resource-policies list --filter='name:*-snap-grp' --format=json --quiet) if ($LASTEXITCODE -ne 0) { throw "gcloud resource-policies list failed (exit code: $LASTEXITCODE)." } $consistencyGroupList = $consistencyGroupListStr | ConvertFrom-Json if (@($consistencyGroupList).Count -eq 0) { throw "No consistency group found matching '*-snap-grp'." } if (@($consistencyGroupList).Count -gt 1) { Write-Warning "More than one consistency group found, using the first one." } $consistencyGroupSelfLink = $consistencyGroupList[0].selfLink $zoneName = Split-Path $vmConfig[0].zone -Leaf $snapshotName = "$($vmConfig.Name)-${formattedTimestamp}" $snapshotCmd = "gcloud compute instant-snapshot-groups create $snapshotName --source-consistency-group=$consistencyGroupSelfLink --zone=$zoneName --quiet" Invoke-Expression $snapshotCmd if ($LASTEXITCODE -ne 0) { throw "gcloud compute instant-snapshot-groups create failed (exit code: $LASTEXITCODE)." } Write-Host "Instant snapshot group created successfully." } catch { Write-Host "Error during snapshot creation: $($_.Exception.Message)" -ForegroundColor Red exit 1 # Exit after handling in finally } # Backup database metadata if (-not (Invoke-MySqlCommand -CommandText $backupMetadataCmd -SqlConnection $sqlConn)) { Write-Host "Failed to backup database metadata." -ForegroundColor Red exit 1 } # Unsuspend Database Write-Host "Unsuspending database '$dbName'..." if (-not (Invoke-MySqlCommand -CommandText $unsuspendDbCmd -SqlConnection $sqlConn)) { Write-Host "Failed to unsuspend database after successful snapshot and metadata backup. Manual intervention may be required." -ForegroundColor Red exit 1 } $databaseSuspended = $false # Successfully unsuspended } catch { Write-Host "An unhandled error occurred: $($_.Exception.Message)" -ForegroundColor Red exit 1 } finally { if ($databaseSuspended -and ($sqlConn.State -eq [System.Data.ConnectionState]::Open)) { if (-not (Invoke-MySqlCommand -CommandText $unsuspendDbCmd -SqlConnection $sqlConn)) { Write-Host "Failed to unsuspend database in finally block. Manual intervention may be required." -ForegroundColor Red } } # Ensure SQL connection is closed if ($sqlConn.State -eq [System.Data.ConnectionState]::Open) { $sqlConn.Close() } }Fai clic con il tasto destro del mouse sul pulsante Start (o premi Win+X) e poi fai clic su Terminale (Amministratore).
Conferma la richiesta di elevazione facendo clic su Sì.
Esegui lo script eseguendo il comando seguente.
C:\scripts\take-snapshot.ps1
Verifica che gli snapshot istantanei siano stati creati
Esegui questi comandi in Cloud Shell:
Verifica che lo script abbia creato gli snapshot.
gcloud compute instant-snapshots list --filter="name:$VM_NAME*"Elenca i gruppi di snapshot istantanei.
gcloud compute instant-snapshot-groups list --zones $ZONEVisualizza i dettagli del gruppo di snapshot istantanei.
gcloud compute instant-snapshot-groups describe \INSTANT_SNAPSHOT_NAME--zone=$ZONECopia il valore
selfLinkda utilizzare nella sezione successiva.
Ripristina gli snapshot istantanei su nuovi dischi
Esegui questi comandi nella Google Cloud finestra della console:
Crea dischi dal gruppo di coerenza degli snapshot istantanei.
gcloud compute disks bulk create --source-instant-snapshot-group \INSTANT_SNAPSHOT_NAME_URL\ --source-instant-snapshot-group-region $REGION --zone=$ZONEVerifica che gli snapshot siano stati ripristinati elencando i dischi nella zona.
gcloud compute disks list --zones=$ZONE --filter="name:$VM_NAME-*"Crea una nuova VM dai dischi appena creati.
REGION=
REGIONZONE=$REGION-a VM_NAME=VM_NAMEgcloud compute instances create $VM_NAME \ --machine-type c4-highmem-4 \ --zone $ZONE \ --network-interface subnet=default \ --tags sql-server-instant-snapshot \ --disk=name=BOOT_DISK_NAME,boot=yes,auto-delete=no \ --disk=name=DATA_DISK_1_NAME,mode=rw,auto-delete=no \ --disk=name=DATA_DISK_2_NAME,mode=rw,auto-delete=no
Sostituisci quanto segue:
- Regione: la regione in cui verrà eseguito il deployment della nuova istanza.
- VM_NAME: il nome della nuova istanza SQL.
- BOOT_DISK_NAME: il nome del disco di avvio creato nel passaggio precedente.
- DATA_DISK_1_NAME: il nome del primo disco dati creato nel passaggio precedente.
- DATA_DISK_2_NAME: il nome del secondo disco dati creato nel passaggio precedente.
Ora puoi collegare i dischi a una VM nuova o esistente.
Libera spazio
Per evitare che al tuo Google Cloud account vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina il progetto.
Elimina il progetto
- Nella Google Cloud console, vai alla pagina Gestisci risorse.
- Nell'elenco dei progetti, seleziona il progetto che vuoi eliminare, quindi fai clic su Elimina.
- Nella finestra di dialogo, digita l'ID progetto, quindi fai clic su Chiudi per eliminare il progetto.
Passaggi successivi
- Esplora architetture di riferimento, diagrammi e best practice su Google Cloud. Consulta il nostro Cloud Architecture Center.