SQL Server mit Instant-Snapshots sichern

Wenn Ihre SQL Server-Datenbankdateien auf mehrere Laufwerke verteilt sind, können Sie alle Laufwerke gleichzeitig sichern und so die Anwendungs- und Datenkonsistenz aufrechterhalten. Diese Sicherung zu einem bestimmten Zeitpunkt wird mit Compute Engine-Konsistenzgruppen von Instant Snapshots erreicht, mit denen Sie Daten auf einer Gruppe von Laufwerken sichern können.

In dieser Anleitung wird beschrieben, wie Sie SQL Server-Datenbanken mit Compute Engine-Snapshots und der Transact-SQL-Snapshotfunktion (T-SQL) sichern, die in SQL Server 2022 und höher verfügbar ist. Diese Lösung unterstützt sowohl Windows- als auch Linux-Bereitstellungen und minimiert die Auswirkungen auf die Leistung Ihrer Live-Arbeitslasten.

Funktionsweise

Der Workflow besteht aus den folgenden Hauptschritten, die von einem Skript verwaltet werden, das auf einer Compute-Instanz ausgeführt wird:

  1. Datenbank einfrieren: Das Skript sendet einen T-SQL-Befehl an SQL Server, um alle Schreibvorgänge für die Zieldatenbank(en) anzuhalten. So wird sichergestellt, dass sich die Datenbankdateien für die Sicherung in einem konsistenten Zustand befinden.
  2. Instant Snapshots erstellen: Während die Datenbank eingefroren ist, erstellen Sie eine Gruppe von Instant Snapshots von den Laufwerken, auf denen sich die Daten- und Protokolldateien der Datenbank befinden. Dies entspricht der Google Cloud Verwendung eines Snapshot-Mechanismus auf Hardware- oder Dienstebene.
  3. Aufzeichnen und auftauen: Das Skript sendet einen weiteren T-SQL-Befehl an SQL Server, um die Sicherungsmetadaten aufzuzeichnen. Mit diesem Befehl wird eine kleine Sicherungsdatei erstellt, die auf die Konsistenz gruppe von Instant Snapshots verweist und im msdbSicherungsverlauf aufgezeichnet wird. Nach Abschluss des Vorgangs, taut SQL Server die Datenbank automatisch auf und setzt den normalen Betrieb fort.

Der gesamte Vorgang ist in der Regel in weniger als einer Sekunde abgeschlossen, wodurch die Dauer des Schreibstopps für Ihre Datenbank minimiert wird. Während des Stopps können Daten gelesen, aber nicht geschrieben werden. Sie können den Stopp manuell beenden, indem Sie SUSPEND_FOR_SNAPSHOT_BACKUP=OFF für die Datenbank festlegen.

Ziele

In dieser Anleitung erfahren Sie, wie Sie die folgenden Aufgaben ausführen:

  • SQL Server-Instanz mit zwei Datenlaufwerken erstellen.
  • Neue Datenbank mit den Daten- und Protokolldateien auf separaten Laufwerken erstellen.
  • Konsistenzgruppe aller Laufwerke der VM erstellen, auf der SQL Server ausgeführt wird.
  • Instant Snapshots der Laufwerksgruppe erstellen.
  • Neue Laufwerke aus den Instant Snapshots erstellen.

Kosten

In diesem Dokument verwenden Sie die folgenden kostenpflichtigen Komponenten von Google Cloud:

Mit dem Preisrechner können Sie eine Kostenschätzung für Ihre voraussichtliche Nutzung vornehmen. Verwenden Sie den Preisrechner.

Neuen Google Cloud Nutzern vonsteht möglicherweise eine kostenlose Testversion zur Verfügung.

Nach Abschluss der in diesem Dokument beschriebenen Aufgaben können Sie weitere Kosten vermeiden, indem Sie die erstellten Ressourcen löschen. Weitere Informationen finden Sie unter Bereinigen.

Hinweis

  1. Für diese Anleitung benötigen Sie ein Google Cloud Projekt. Sie können ein neues Projekt erstellen oder ein vorhandenes Projekt auswählen:

    1. Wählen Sie in der Google Cloud Console auf der Seite für die Projektauswahl ein Projekt aus oder erstellen Sie eines. Google Cloud

      Rollen, die zum Auswählen oder Erstellen eines Projekts erforderlich sind

      • Projekt auswählen: Für die Auswahl eines Projekts ist keine bestimmte IAM-Rolle erforderlich. Sie können jedes Projekt auswählen, für das Ihnen eine Rolle zugewiesen wurde.
      • Projekt erstellen: Zum Erstellen eines Projekts benötigen Sie die Rolle „Projektersteller“ (roles/resourcemanager.projectCreator), die die resourcemanager.projects.create Berechtigung enthält. Informationen zum Zuweisen von Rollen.

      Zur Projektauswahl

    2. Prüfen Sie, ob für Ihr Google Cloud Projekt die Abrechnung aktiviert ist.

    3. Aktivieren Sie Cloud Shell in der Google Cloud Console.

      Cloud Shell aktivieren

  2. Prüfen Sie, ob Microsoft SQL Server 2022 oder höher installiert ist und ausgeführt wird.

Erforderliche Berechtigungen

Zusätzlich zum Standardlesezugriff muss Ihr SQL Server-Administrator Ihnen die Berechtigung ALTER DATABASE für die Zieldatenbank gewähren.

Bitten Sie Ihren Administrator, Ihnen die folgenden IAM-Rollen für das Projekt zuzuweisen, um die Berechtigungen zu erhalten, die Sie zum Erstellen einer Instanz und zum Erstellen von Snapshots benötigen:

  • Instanz verwalten: compute.instanceAdmin.v1
  • Snapshots erstellen: compute.storageAdmin

Weitere Informationen zum Zuweisen von Rollen finden Sie unter Zugriff auf Projekte, Ordner und Organisationen verwalten.

Sie können die erforderlichen Berechtigungen auch über benutzerdefinierte Rollen oder andere vordefinierte Rollen erhalten.

Compute Engine-SQL-Instanz erstellen

Erstellen Sie eine SQL Server-Instanz.

  1. Öffnen Sie in der Google Cloud Console Cloud Shell. Klicken Sie hierzu auf den Button Cloud Shell aktivieren Aktivieren Sie Cloud Shell..

    Rufen Sie die Google Cloud Console auf.

  2. Erstellen Sie eine SQL Server-Instanz. Fügen Sie den folgenden Befehl ein:

  REGION=REGION
  ZONE=$REGION-a
  VM_NAME=VM_NAME
  gcloud 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

Ersetzen Sie Folgendes:

  • Region: Die Region, in der die neue Instanz bereitgestellt wird.
  • VM_NAME: Der Name der neuen SQL Server-Instanz.

Konsistenzgruppe von Laufwerken erstellen

  1. Erstellen Sie eine Konsistenzgruppe.

    gcloud compute resource-policies create disk-consistency-group $VM_NAME-snap-grp \
        --region=$REGION
    
  2. Fügen Sie die Laufwerke der VM der Konsistenzgruppe hinzu.

    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
    

Neue Datenbank erstellen

  1. Erstellen Sie einen Nutzernamen und ein Passwort für die VM-Instanz.
  2. Stellen Sie mithilfe von Remote Desktop eine Verbindung zur VM her und melden Sie sich mit dem Nutzernamen und dem Passwort an, den bzw. das Sie im vorherigen Schritt erstellt haben.
  3. Klicken Sie mit der rechten Maustaste auf die Schaltfläche Start (oder drücken Sie Win + X) und klicken Sie auf Terminal (Administrator).
  4. Bestätigen Sie die Eingabeaufforderung für erhöhte Rechte durch Klicken auf Ja.
  5. Führen Sie das folgende PowerShell-Skript im geöffneten Terminalfenster aus. Mit diesem Skript wird das Datenlaufwerk initialisiert, mit einer Blockgröße von 64 KB formatiert und ein Laufwerkbuchstabe zugewiesen.

    $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
    }
    
  6. Öffnen Sie SQL Server Management Studio (SSMS). Führen Sie es als Administrator aus.

  7. Prüfen Sie im Dialogfeld „Mit Server verbinden“, ob der Servername auf localhost festgelegt ist, und wählen Sie Verbinden aus.

  8. Wählen Sie im Menü „Datei“ die Option Datei > Neu > Abfrage mit der aktuellen Verbindung aus.

  9. Kopieren Sie den folgenden Code in das neu geöffnete Abfragefenster.

    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
    );
    

Snapshot-Skript bereitstellen

Dieses Skript automatisiert den gesamten Prozess, der erforderlich ist, um anwendungskonsistente Snapshots der Laufwerke zu erstellen, die an die VM angehängt sind, auf der SQL Server ausgeführt wird.

  1. Öffnen Sie in derselben Remotedesktopsitzung den Editor.
  2. Kopieren Sie den Inhalt des folgenden Skripts und fügen Sie ihn in das geöffnete Editorfenster ein.
  3. Speichern Sie die Datei als take-snapshot.ps1 in c:\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()
        }
    }
    
    
  4. Klicken Sie mit der rechten Maustaste auf die Schaltfläche Start (oder drücken Sie Win + X) und klicken Sie auf Terminal (Administrator).

  5. Bestätigen Sie die Eingabeaufforderung für erhöhte Rechte durch Klicken auf Ja.

  6. Führen Sie das Skript mit dem folgenden Befehl aus.

        C:\scripts\take-snapshot.ps1
    

Prüfen, ob die Instant Snapshots erstellt wurden

Führen Sie die folgenden Befehle in Cloud Shell aus:

  1. Prüfen Sie, ob das Skript die Snapshots erstellt hat.

        gcloud compute instant-snapshots list --filter="name:$VM_NAME*"
    
  2. Listen Sie die Instant Snapshot-Gruppen auf.

        gcloud compute instant-snapshot-groups list --zones $ZONE
    
  3. Details zur Instant Snapshot-Gruppe ansehen.

        gcloud compute instant-snapshot-groups describe  \
        INSTANT_SNAPSHOT_NAME --zone=$ZONE
    
  4. Kopieren Sie den Wert selfLink, um ihn im nächsten Abschnitt zu verwenden.

Instant Snapshots auf neuen Laufwerken wiederherstellen

Führen Sie die folgenden Befehle im Google Cloud Console-Fenster aus:

  1. Erstellen Sie Laufwerke aus der Konsistenzgruppe von Instant Snapshots.

        gcloud compute disks bulk create --source-instant-snapshot-group \
        INSTANT_SNAPSHOT_NAME_URL \
        --source-instant-snapshot-group-region $REGION --zone=$ZONE
    
  2. Prüfen Sie, ob Ihre Snapshots wiederhergestellt wurden, indem Sie die Laufwerke in der Zone auflisten.

        gcloud compute disks list --zones=$ZONE --filter="name:$VM_NAME-*"
    
  3. Erstellen Sie eine neue VM aus den neu erstellten Laufwerken.

    REGION=REGION
    ZONE=$REGION-a
    VM_NAME=VM_NAME
    gcloud 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
    

Ersetzen Sie Folgendes:

  • Region: Die Region, in der die neue Instanz bereitgestellt wird.
  • VM_NAME: Der Name der neuen SQL-Instanz.
  • BOOT_DISK_NAME: Der Name des im vorherigen Schritt erstellten Bootlaufwerks.
  • DATA_DISK_1_NAME: Der Name des ersten im vorherigen Schritt erstellten Datenlaufwerks.
  • DATA_DISK_2_NAME: Der Name des zweiten im vorherigen Schritt erstellten Datenlaufwerks.

Sie können die Laufwerke jetzt anhängen an eine neue oder vorhandene VM.

Bereinigen

Löschen Sie das Projekt, damit Ihrem Google Cloud Konto die in dieser Anleitung verwendeten Ressourcen nicht in Rechnung gestellt werden:

Projekt löschen

  1. Wechseln Sie in der Google Cloud Console zur Seite Ressourcen verwalten.

    Zur Seite „Ressourcen verwalten“

  2. Wählen Sie in der Projektliste das Projekt aus, das Sie löschen möchten, und klicken Sie dann auf Löschen.
  3. Geben Sie im Dialogfeld die Projekt-ID ein und klicken Sie auf Shut down (Herunterfahren), um das Projekt zu löschen.

Nächste Schritte

  • Referenzarchitekturen, Diagramme und Best Practices zu Google Cloud kennenlernen. Weitere Informationen zu Cloud Architecture Center