Crea copias de seguridad de SQL Server con instantáneas

Si los archivos de la base de datos de SQL Server están distribuidos en varios discos, puedes crear una copia de seguridad de todos los discos de forma simultánea y mantener la coherencia de la aplicación y los datos. Puedes lograr esta copia de seguridad exacta en un momento determinado con los grupos de coherencia de instantáneas de Compute Engine, que te permiten crear copias de seguridad de los datos en un grupo de discos.

En este instructivo, se describe cómo crear copias de seguridad de bases de datos de SQL Server con instantáneas de Compute Engine y la función de instantáneas de Transact-SQL (T-SQL) que está disponible en SQL Server 2022 y versiones posteriores. Esta solución admite implementaciones de Windows y Linux, y minimiza el impacto en el rendimiento de tus cargas de trabajo en vivo.

Cómo funciona

El flujo de trabajo consta de estos pasos principales, que se administran con una secuencia de comandos que se ejecuta en una instancia de procesamiento:

  1. Congela la base de datos: La secuencia de comandos envía un comando T-SQL a SQL Server para suspender todas las operaciones de escritura de las bases de datos de destino. Esto garantiza que los archivos de la base de datos estén en un estado coherente para la copia de seguridad.
  2. Toma instantáneas: Mientras la base de datos está congelada, crea un grupo de instantáneas de los discos en los que residen los datos y los archivos de registro de la base de datos. Esto equivale a usar un mecanismo de instantáneas de hardware o de nivel de servicio. Google Cloud
  3. Registra y descongelar: La secuencia de comandos envía otro comando T-SQL a SQL Server para registrar los metadatos de la copia de seguridad. Este comando crea un archivo de copia de seguridad pequeño que apunta al grupo de coherencia de instantáneas y se registra en el historial de copias de seguridad de msdb. Una vez completado, SQL Server descongelará automáticamente la base de datos y reanudará las operaciones normales.

Por lo general, todo este proceso se completa en menos de un segundo, lo que minimiza la duración de la congelación de escritura en tu base de datos. Mientras la congelación esté en su lugar, se pueden leer los datos, pero no se pueden escribir. Puedes cancelar manualmente el estado de congelación si configuras SUSPEND_FOR_SNAPSHOT_BACKUP=OFF para la base de datos.

Objetivos

En este instructivo, aprenderás a completar las siguientes tareas:

  • Crea una instancia de SQL Server con dos discos de datos.
  • Crea una base de datos nueva con los datos y los archivos de registro en discos separados.
  • Crea un grupo de coherencia de todos los discos de la VM que ejecuta SQL Server.
  • Crea instantáneas del grupo de discos.
  • Crea discos nuevos a partir de las instantáneas.

Costos

En este documento, usarás los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios.

Es posible que los usuarios de Google Cloud nuevos cumplan con los requisitos para acceder a una prueba gratuita.

Cuando completes las tareas que se describen en este documento, podrás borrar los recursos que creaste para evitar que se te siga facturando. Para obtener más información, consulta Realiza una limpieza.

Antes de comenzar

  1. Para este instructivo, necesitas un Google Cloud proyecto. Puedes crear uno nuevo o seleccionar uno existente:

    1. En la Google Cloud consola de, en la página del selector de proyectos, selecciona o crea un Google Cloud proyecto.

      Roles necesarios para seleccionar o crear un proyecto

      • Seleccionar un proyecto: Para seleccionar un proyecto, no se requiere un rol de IAM específico. Puedes seleccionar cualquier proyecto en el que se te haya otorgado un rol.
      • Crear un proyecto: Para crear un proyecto, necesitas el rol de creador de proyectos (roles/resourcemanager.projectCreator), que contiene el resourcemanager.projects.create permiso. Obtén más información para otorgar roles.

      Ir al selector de proyectos

    2. Verifica que la facturación esté habilitada para tu Google Cloud proyecto.

    3. En la Google Cloud consola, activa Cloud Shell.

      Activa Cloud Shell

  2. Asegúrate de que Microsoft SQL Server 2022 o una versión posterior esté instalado y en ejecución.

Permisos necesarios

Además del acceso de lectura estándar, asegúrate de que el administrador de SQL Server te otorgue el permiso ALTER DATABASE para la base de datos de destino.

Para obtener los permisos que necesitas para crear instancias y crear instantáneas, pídele a tu administrador que te otorgue los siguientes roles de IAM en el proyecto:

  • Administrar instancias: compute.instanceAdmin.v1
  • Crear instantáneas: compute.storageAdmin

Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.

También puedes obtener los permisos necesarios mediante roles personalizados o cualquier otro rol predefinido.

Crea una instancia de SQL de Compute Engine

Crea una instancia de SQL Server.

  1. En la Google Cloud consola, haz clic en el botón Activar Cloud Shell Activar Cloud Shell. para abrir Cloud Shell.

    Ir a la Google Cloud consola

  2. Crea una instancia de SQL Server. Pega el siguiente comando:

  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

Reemplaza lo siguiente:

  • Región: La región en la que se implementará tu instancia nueva.
  • VM_NAME: El nombre de tu nueva instancia de SQL Server.

Crea un grupo de coherencia de discos

  1. Crea un grupo de coherencia.

    gcloud compute resource-policies create disk-consistency-group $VM_NAME-snap-grp \
        --region=$REGION
    
  2. Agrega los discos de la VM al grupo de coherencia.

    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
    

Crear una base de datos nueva

  1. Crea un nombre de usuario y una contraseña para la instancia de VM.
  2. Conéctate a la VM mediante el escritorio remoto y accede con el nombre de usuario y la contraseña que creaste en el paso anterior.
  3. Haz clic con el botón derecho en el botón Inicio (o presiona Win+X) y, luego, en Terminal (administrador).
  4. Para confirmar el símbolo de elevación, haz clic en .
  5. Ejecuta la siguiente secuencia de comandos de PowerShell en la ventana de la terminal abierta. Esta secuencia de comandos inicializa el disco de datos, lo formatea con un tamaño de bloque de 64 KB y asigna una letra de unidad.

    $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. Abre SQL Server Management Studio (SSMS). Ejecútalo como administrador.

  7. En el cuadro de diálogo Conectar al servidor, verifica que el nombre del servidor esté configurado como localhost y selecciona Conectar.

  8. En el menú de archivo, selecciona Archivo > Nuevo > Consulta con la conexión actual.

  9. Copia el siguiente código en la ventana de consulta recién abierta.

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

Implementa la secuencia de comandos de instantáneas

Esta secuencia de comandos automatiza el proceso completo necesario para tomar instantáneas coherentes con la aplicación de los discos conectados a la VM que ejecuta SQL Server.

  1. Con la misma sesión de Escritorio remoto, abre el Bloc de notas.
  2. Copia el contenido de la siguiente secuencia de comandos y pégalo en la ventana del Bloc de notas abierta.
  3. Guarda el archivo como take-snapshot.ps1 en 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. Haz clic con el botón derecho en el botón Inicio (o presiona Win+X) y, luego, en Terminal (administrador).

  5. Para confirmar el símbolo de elevación, haz clic en .

  6. Ejecuta la secuencia de comandos con el siguiente comando.

        C:\scripts\take-snapshot.ps1
    

Verifica que se hayan creado las instantáneas

Ejecuta los siguientes comandos en Cloud Shell.

  1. Verifica que la secuencia de comandos haya creado las instantáneas.

        gcloud compute instant-snapshots list --filter="name:$VM_NAME*"
    
  2. Enumera los grupos de instantáneas inmediatas.

        gcloud compute instant-snapshot-groups list --zones $ZONE
    
  3. Visualiza los detalles del grupo de instantáneas inmediatas.

        gcloud compute instant-snapshot-groups describe  \
        INSTANT_SNAPSHOT_NAME --zone=$ZONE
    
  4. Copia el valor de selfLink para usarlo en la siguiente sección.

Restablece las instantáneas en discos nuevos

Ejecuta los siguientes comandos en la Google Cloud ventana de la consola.

  1. Crea discos a partir del grupo de coherencia de instantáneas.

        gcloud compute disks bulk create --source-instant-snapshot-group \
        INSTANT_SNAPSHOT_NAME_URL \
        --source-instant-snapshot-group-region $REGION --zone=$ZONE
    
  2. Para confirmar que se restablecieron las instantáneas, enumera los discos en la zona.

        gcloud compute disks list --zones=$ZONE --filter="name:$VM_NAME-*"
    
  3. Crea una VM nueva a partir de los discos recién creados.

    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
    

Reemplaza lo siguiente:

  • Región: La región en la que se implementará tu instancia nueva.
  • VM_NAME: El nombre de tu nueva instancia de SQL.
  • BOOT_DISK_NAME: El nombre del disco de arranque creado en el paso anterior.
  • DATA_DISK_1_NAME: El nombre del primer disco de datos creado en el paso anterior.
  • DATA_DISK_2_NAME: El nombre del segundo disco de datos creado en el paso anterior.

Ahora puedes conectar los discos a una VM nueva o existente.

Limpia

Para evitar que se apliquen cargos a tu Google Cloud cuenta por los recursos que usaste en este instructivo, borra el proyecto.

Borra el proyecto

  1. En la Google Cloud consola, ve a la página Administrar recursos.

    Ir a Administrar recursos

  2. En la lista de proyectos, elige el proyecto que deseas borrar y haz clic en Borrar.
  3. En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrarlo.

¿Qué sigue?

  • Explora arquitecturas de referencia, diagramas y prácticas recomendadas sobre Google Cloud. Consulta nuestro Cloud Architecture Center.