Sauvegarder SQL Server à l'aide d'instantanés

Si vos fichiers de base de données SQL Server sont répartis sur plusieurs disques, vous pouvez sauvegarder tous les disques simultanément, en conservant la cohérence des applications et des données. Vous pouvez effectuer cette sauvegarde à un moment précis grâce aux groupes de cohérence d'instantanés immédiats de Compute Engine, qui vous permettent de sauvegarder des données sur un groupe de disques.

Ce tutoriel explique comment sauvegarder des bases de données SQL Server avec des instantanés Compute Engine et la fonctionnalité d'instantané Transact-SQL (T-SQL) disponible dans SQL Server 2022 et versions ultérieures. Cette solution est compatible avec les déploiements Windows et Linux, et minimise l'impact sur les performances de vos charges de travail en direct.

Fonctionnement

Le workflow se compose des étapes principales suivantes, qui sont gérées par un script s'exécutant sur une instance de calcul :

  1. Geler la base de données : le script envoie une commande T-SQL à SQL Server pour suspendre toutes les opérations d'écriture pour la ou les bases de données cibles. Cela garantit que les fichiers de base de données sont dans un état cohérent pour la sauvegarde.
  2. Prendre des instantanés immédiats : pendant que la base de données est gelée, créez un groupe d'instantanés immédiats de s disques sur lesquels résident les fichiers de données et journaux de la base de données. Cela équivaut à utiliser un mécanisme d'instantané au niveau du matériel ou du service. Google Cloud
  3. Enregistrer et décongeler : le script envoie une autre commande T-SQL à SQL Server pour enregistrer les métadonnées de sauvegarde. Cette commande crée un petit fichier de sauvegarde qui pointe vers le groupe de cohérence d'instantanés immédiats et est enregistré dans l'historique de sauvegarde msdb. Une fois l'opération terminée, SQL Server décongèle automatiquement la base de données et reprend ses opérations normales.

L'ensemble de ce processus est généralement effectué en moins d'une seconde, ce qui minimise la durée du gel d'écriture sur votre base de données. Pendant le gel, les données peuvent être lues, mais pas écrites. Vous pouvez annuler manuellement l'état de gel en définissant SUSPEND_FOR_SNAPSHOT_BACKUP=OFF pour la base de données.

Objectifs

Dans ce tutoriel, vous apprendrez à effectuer les tâches suivantes :

  • Créer une instance SQL Server avec deux disques de données.
  • Créer une base de données avec les fichiers de données et journaux sur des disques distincts.
  • Créer un groupe de cohérence de tous les disques de la VM exécutant SQL Server.
  • Créer des instantanés immédiats du groupe de disques.
  • Créer des disques à partir des instantanés immédiats.

Coûts

Dans ce document, vous utilisez les composants facturables de suivants Google Cloud:

Obtenez une estimation des coûts en fonction de votre utilisation prévue, utilisez le simulateur de coût.

Les nouveaux utilisateurs de peuvent bénéficier d'un essai sans frais. Google Cloud

Une fois que vous avez terminé les tâches décrites dans ce document, supprimez les ressources que vous avez créées pour éviter que des frais vous soient facturés. Pour en savoir plus, consultez la section Effectuer un nettoyage.

Avant de commencer

  1. Pour ce tutoriel, vous avez besoin d'un Google Cloud projet. Vous pouvez en créer un, ou en sélectionner un existant :

    1. Dans la Google Cloud console, sur la page de sélection du projet, sélectionnez ou créez un Google Cloud projet.

      Rôles requis pour sélectionner ou créer un projet

      • Sélectionner un projet : la sélection d'un projet ne nécessite pas de rôle IAM spécifique Vous pouvez sélectionner n'importe quel projet pour lequel un rôle vous a été attribué.
      • Créer un projet : pour créer un projet, vous avez besoin du rôle Créateur de projet (roles/resourcemanager.projectCreator), qui contient l'autorisation resourcemanager.projects.create. Découvrez comment attribuer des rôles.

      Accéder au sélecteur de projet

    2. Vérifiez que la facturation est activée pour votre Google Cloud projet.

    3. Dans la Google Cloud console, activez Cloud Shell.

      Activer Cloud Shell

  2. Assurez-vous que Microsoft SQL Server 2022 ou version ultérieure est installé et en cours d'exécution.

Autorisations requises

En plus de l'accès en lecture standard, assurez-vous que votre administrateur SQL Server vous accorde l'autorisation ALTER DATABASE pour la base de données cible.

Pour obtenir les autorisations nécessaires pour créer une instance et des instantanés, demandez à votre administrateur de vous accorder les rôles IAM suivants sur le projet :

  • Gérer l'instance : compute.instanceAdmin.v1
  • Créer des instantanés : compute.storageAdmin

Pour en savoir plus sur l'attribution de rôles, consultez Gérer l'accès aux projets, aux dossiers et aux organisations.

Vous pouvez également obtenir les autorisations requises avec des rôles personnalisés ou d'autres rôles prédéfinis.

Créer une instance SQL Compute Engine

Créez une instance SQL Server.

  1. Dans la console Google Cloud , ouvrez Cloud Shell en cliquant sur le bouton Activer Cloud Shell Activez Cloud Shell..

    Accéder à la Google Cloud console

  2. Créez une instance SQL Server. Collez la commande suivante :

  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

Remplacez les éléments suivants :

  • Région : région dans laquelle votre nouvelle instance sera déployée.
  • VM_NAME : nom de votre nouvelle instance SQL Server.

Créer un groupe de cohérence de disques

  1. Créez un groupe de cohérence.

    gcloud compute resource-policies create disk-consistency-group $VM_NAME-snap-grp \
        --region=$REGION
    
  2. Ajoutez les disques de la VM au groupe de cohérence.

    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
    

Créer une base de données

  1. Créez un nom d'utilisateur et un mot de passe pour l'instance de VM.
  2. Connectez-vous à la VM à l'aide du Bureau à distance en vous servant du nom d'utilisateur et du mot de passe créés à l'étape précédente.
  3. Effectuez un clic droit sur le bouton Démarrer (ou appuyez sur Win+X) et cliquez sur Terminal (Administrateur).
  4. Confirmez l'invite d'élévation en cliquant sur Yes (Oui).
  5. Exécutez le script PowerShell suivant dans la fenêtre de terminal ouverte. Ce script initialise le disque de données, le formate avec une taille de bloc de 64 Ko et lui attribue une lettre de lecteur.

    $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. Ouvrez SQL Server Management Studio (SSMS). Exécutez-le en tant qu'administrateur.

  7. Dans la boîte de dialogue Se connecter au serveur, vérifiez que le nom du serveur est défini sur localhost et sélectionnez Se connecter.

  8. Dans le menu Fichier, sélectionnez Fichier > Nouveau > Requête avec la connexion actuelle.

  9. Copiez le code suivant dans la fenêtre de requête qui vient de s'ouvrir.

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

Déployer le script d'instantané

Ce script automatise l'ensemble du processus requis pour prendre des instantanés cohérents avec les applications des disques associés à la VM exécutant SQL Server.

  1. Dans la même session de bureau à distance, ouvrez le Bloc-notes.
  2. Copiez le contenu du script suivant et collez-le dans la fenêtre du Bloc-notes ouverte.
  3. Enregistrez le fichier sous le nom take-snapshot.ps1 dans 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. Effectuez un clic droit sur le bouton Démarrer (ou appuyez sur Win+X) et cliquez sur Terminal (Administrateur).

  5. Confirmez l'invite d'élévation en cliquant sur Yes (Oui).

  6. Exécutez le script en exécutant la commande suivante.

        C:\scripts\take-snapshot.ps1
    

Vérifier que les instantanés immédiats ont été créés

Exécutez les commandes suivantes dans Cloud Shell.

  1. Vérifiez que le script a créé les instantanés.

        gcloud compute instant-snapshots list --filter="name:$VM_NAME*"
    
  2. Répertoriez les groupes d'instantanés immédiats.

        gcloud compute instant-snapshot-groups list --zones $ZONE
    
  3. Affichez les détails du groupe d'instantanés immédiats.

        gcloud compute instant-snapshot-groups describe  \
        INSTANT_SNAPSHOT_NAME --zone=$ZONE
    
  4. Copiez la valeur selfLink à utiliser dans la section suivante.

Restaurer les instantanés immédiats sur de nouveaux disques

Exécutez les commandes suivantes dans la Google Cloud fenêtre de la console.

  1. Créez des disques à partir du groupe de cohérence d'instantanés immédiats.

        gcloud compute disks bulk create --source-instant-snapshot-group \
        INSTANT_SNAPSHOT_NAME_URL \
        --source-instant-snapshot-group-region $REGION --zone=$ZONE
    
  2. Vérifiez que vos instantanés ont été restaurés en listant les disques de la zone.

        gcloud compute disks list --zones=$ZONE --filter="name:$VM_NAME-*"
    
  3. Créez une VM à partir des disques nouvellement créés.

    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
    

Remplacez les éléments suivants :

  • Région : région dans laquelle votre nouvelle instance sera déployée.
  • VM_NAME : nom de votre nouvelle instance SQL.
  • BOOT_DISK_NAME : nom du disque de démarrage créé à l'étape précédente.
  • DATA_DISK_1_NAME : nom du premier disque de données créé à l'étape précédente.
  • DATA_DISK_2_NAME : nom du deuxième disque de données créé à l'étape précédente.

Vous pouvez maintenant associer les disques à une VM nouvelle ou existante.

Libérer de l'espace

Pour éviter que les ressources utilisées lors de ce tutoriel ne soient facturées sur votre Google Cloud compte, supprimez le projet.

Supprimer le projet

  1. Dans la Google Cloud console, accédez à la page Gérer les ressources.

    Accéder à la page "Gérer les ressources"

  2. Dans la liste des projets, sélectionnez le projet que vous souhaitez supprimer, puis cliquez sur Supprimer.
  3. Dans la boîte de dialogue, saisissez l'ID du projet, puis cliquez Arrêter pour supprimer le projet.

Étape suivante

  • Découvrez des architectures de référence, des schémas et des bonnes pratiques concernant Google Cloud. Consultez notre Cloud Architecture Center.