Using T-SQL Snapshot Backup: Point-in-time Recovery – Azure Edition

The third post in this series walks you through the process for using the T-SQL snapshot backup feature in SQL Server 2022 for point-in-time recovery of a database in an Azure Virtual Machine.

T-SQL Snapshot Backup

10 minutes

Summary

T-SQL snapshot backup is a new feature in SQL Server 2022 that enables you to take a snapshot backup. You can then perform point-in-time recovery of a database in an Azure Virtual Machine using that snapshot backup as the base for recovery.

image_pdfimage_print

This blog on T-SQL snapshot backups originally appeared on www.nocentino.com. It has been republished with permission from the author.

In this post, the third in our series, I will guide you through using the new T-SQL snapshot backup feature in SQL Server 2022 to take a snapshot backup and then perform point-in-time database restores using that snapshot backup as the base, but this time using an Azure Virtual Machine. We will explore how to manage Azure storage-level operations, such as taking snapshots, cloning snapshots, and executing an instantaneous point-in-time database restore from the snapshot with minimal impact on your infrastructure. Additionally, I will demonstrate a PowerShell script that utilizes dbatools and Azure Az modules to automate the process.

You can grab the whole script for this blog post on GitHub.

Taking a T-SQL Snapshot Backup

In the previous posts in this series, Using T-SQL Snapshot Backup: Are Snapshots Backups?” and “Using T-SQL Snapshot Backup: Point-in-time Recovery,” we covered the theory of using T-SQL snapshot backup for backup and restore operations and also how to use this technique on a Pure Storage® FlashArray™ system and Pure Cloud Block Store™. Now it’s time to look at how to use T-SQL snapshot backup in Azure Virtual Disks. Let’s get started…

Initialize the Script’s Variables and Connections

  • To begin, we’ll set up some PowerShell variables to establish connections to our SQL Server and also Azure. I’m utilizing dbatools and the Az PowerShell module to manage this process.
  • Now, let’s start by connecting to Azure using the cmdlet Connect-AzAccount. After that, we can create a persistent SMO connection to our SQL Server instance using Connect-DbaInstance just like we have done in previous posts. Lastly, we’ll need to work on Azure Virtual Machine storage configuration tasks, so we’ll start by getting a reference to our virtual machine in Azure using the command Get-VM.

Connect to Our Storage Environment in Azure

  • First, get the names of the Azure Virtual Disk data disks connected to our virtual machine. Ensure you retrieve all disks containing the database files (data and log) of the database you intend to snapshot. On this system, we have two virtual disks: one for the database files and one for the transaction log file. In the output, you can see our disks are named Sql1_DataDisk_0 and Sql1_DataDisk_1. Azure tools and documentation refer to any non-operating system volume as a data disk.
  • Use the above names to reference the Azure Virtual Disk resources, which will serve as the base for our clone operation. The output below shows the URIs for the Azure Virtual Disk resources we want to work with.

Let’s Create a Snapshot Config

  • Now, let’s create a snapshot configuration with the New-AzSnapshotConfig cmdlet. This cmdlet sets up the configuration parameters for the snapshot, including its source, location, and type of snapshot. Later, this configuration will be used with New-AzSnapshot to create the snapshot. The SourceUri parameter uses the Azure Virtual Disk URIs from the previous code block. The Location parameter specifies the Azure region where the snapshot will be created. The CreateOption parameter determines that the snapshot type should be created as a copy of the source disk, using Copy. There are many options for the New-AzSnapshotConfig cmdlet, check out the docs for more details. This is where you can set options to replicate your snapshots to other regions in Azure.

Taking a T-SQL-based Snapshot Backup

  • With our snapshot configuration set, let’s proceed with the T-SQL-based snapshot backup process by putting the data in SUSPEND_FOR_SNAPSHOT_BACKUP mode to freeze write IO.
  • Now, use the New-AzSnapshot command to create a snapshot of each of the virtual machines’ data disks using the previously defined snapshot configuration. The -SnapshotName parameter should use the dynamically generated name stored in the $DataSnapshotName variable. Then, use the -Snapshot parameter to refer to the previously built snapshot configuration. Finally, specify the Azure resource group where the snapshot will be created using the -ResourceGroupName parameter. Here, we take a snapshot of Sql1_DataDisk_0 and Sql1_DataDisk_1.
  • Now, it’s time to take a metadata-only backup. The metadata-only backup file name is dynamically generated using the database name and the current date. The backup command contains the database name $DbName, the backup file location TO DISK=’$BackupFile’, and the WITH METADATA_ONLY option to specify that it’s a snapshot backup without copying the data. The MEDIADESCRIPTION part stores the Azure snapshot name and URI in the backup metadata as a pipe-delimited string. This information can help locate the snapshot associated with this metadata-only backup file. Finally, the T-SQL snapshot backup is executed using the cmdlet Invoke-DbaQuery, which writes the metadata-only backup file to the specified location after thawing the database if successful.
    I am using the verbose flag again. When the command is executed, the output will show that the database is thawed, write IO is resumed, and the backup locks are released. Additionally, it will produce output similar to that of a full backup, reporting the number of pages copied from the database files. However, in this case, it will show that 0 pages are copied because we are performing a METADATA_ONLY snapshot backup.
  • Now that we have a snapshot backup as a base for a full database restore, let’s take a log backup so that we can later showcase how to perform a point-in-time recovery.
  • With the snapshot created, you can use the command Get-AzSnapshot -ResourceGroupName $ResourceGroupName to retrieve the snapshots available within the specified resource group. In the following output, you will find both snapshots of our virtual machine disks.

What Does SQL Server Think Happened?

Let’s check the SQL Server error log to see what SQL Server thinks happened. Here, you can see that the snapshot backup process begins for Database1. The database option suspend_for_snapshot_backup is set to ON, and the database acquires backup locks, and freezes I/O operations. Then, after we take our METADATA_ONLY snapshot backup, the I/O operations for Database1 are resumed, and the backup locks are released. The log reports that the backup operation completes successfully, and we see that again 0 pages are being copied.

  • Let’s check out the error log to see what SQL Server thinks happened.
  • The backup is recorded in MSDB as a full backup with a snapshot.
  • Let’s take a look at the information in the backup header. Here, I’ve summarized important details such as BackupType, BackupPath, and data size. This header format is consistent across all backup types in SQL Server. As you develop automation processes around this feature, it should be familiar territory for a DBA.
snapshots backups
Point-in-time Recovery
T-SQL Snapshot Backup

Performing a Point-in-time Restore from a T-SQL Snapshot Backup

Performing the restore is a storage-level operation that requires work both inside the operating system and Azure. First, inside the operating system you need to take the database and disks offline. Then, in Azure, you need to detach the Azure Virtual Disks from the virtual machine. After detaching the disks, you must clone the snapshot to new virtual disks, ensuring that the configuration matches your performance and availability requirements. Then, you can attach the new cloned disks to your virtual machine. Once the disks are attached, bring them online in Windows and proceed with the T-SQL snapshot restore process. Let’s take a look at how to accomplish all of this in code.

  • First, we need to take the database offline, which we’d have to do anyway if we were restoring a full backup.
  • Since this is a storage-level operation for the Azure disks, the volumes containing database files need to be taken offline. You will need to update the disk number to match those in your VM.
  • Now that the database is offline and the disks holding the database files are also offline, you need to remove the disks from the virtual machine. You can do this by using the Remove-AzVMDataDisk command and specifying a reference to the virtual machine using the -VM parameter. Then, you can pass in the name of the disks to detach using the Name parameter. Once those disks are marked for removal, you can use the Update-AzVM command to apply this change to the virtual machine and remove the disks.
  • To create our two new Azure virtual disks from our snapshots, we define a disk configuration using New-AzDiskConfig. The -SourceResourceID is the snapshot’s ID. We should also consider the configuration of the previous disks for location, storage type (SKU), and availability zone. This needs to match the previous disks’ configuration if you are attaching back to the same virtual machine and your performance requirements are still the same. Then, we pass the configuration into the New-AzDisk cmdlet to create the new disk. These new virtual disks will have the data on them from the point in time of the snapshots taken earlier.
  • Now that the disks are created with the data from the snapshots created earlier, let’s attach them to the VM using Add-AzVMDataDisk. One of the best practices for SQL Server Virtual Machines in Azure is to use read-caching on the database volume, which can be enabled by using the -Caching parameter and setting the caching policy to ReadWrite on the Set-AzVMDataDisk command. However, caching should not be used on the transaction log volume. After attaching the disks and setting the caching policy, you need to update your VM’s disk configuration with Update-AzVM.
  • With all the Azure storage work completed, let’s go online with the disks. The database files are now available inside the OS, reverted back in time, and ready to perform our T-SQL-based snapshot point-in-time restore process.
  • With the database files physically in place and reverted back in time, we can use the following code to create the RESTORE command as a string: RESTORE DATABASE $DbName to initiate the restore process, and specify the location of the metadata-only backup file using the FROM DISK = ‘$BackupFile’ option. Since this is a T-SQL snapshot backup-based restore, we need to include the METADATA_ONLY option, which informs the database engine not to copy the pages during the restore process. Additionally, we should incorporate the REPLACE option to overwrite the existing database and include the NORECOVERY option to keep the database in RESTORING mode after the command is executed. If you wish to bring the database online at this point, you can omit the NORECOVERY option. The Invoke-DbaQuery command is used to execute the query string and initiates the restore process.
  • The full restore duration includes the instant snapshot revert and about half a second of database operations. That’s just wild!
  • With the full restore completed, let’s check the database’s current status. It’s in RESTORING mode.
  • Now, it’s time to perform the log restore. I am leaving the database in the RESTORING mode by adding the -NoRecovery parameter.
  • Online the database; we’ve just completed a point-in-time restore.
  • Let’s again check the current state of the database…it’s ONLINE.

Wrapping Things Up

In this post, which is the third in our series, we used the T-SQL snapshot backup feature for point-in-time recovery of a database in an Azure Virtual Machine. Consider the business impact of this capability. You can perform an instantaneous full database restore and control your precise recovery point with a point-in-time restore.

You can grab the whole script for this blog post on GitHub.