09/30/2024 | Press release | Distributed by Public on 09/30/2024 15:16
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
1 |
Import-Module dbatools $TenantId = '1d192baa-aca4-4727-ab9f-290398d9564c' #My super secret TenantId, or is it? $Location = 'CentralUS' #Region for our VM $ResourceGroupName = 'Sql1_group' #Resource group for our VM $TargetSQLServer = 'Sql1' #Virtual Machine name in Azure $DbName = 'Database1' # Name of database $BackupShare = '\\FileServer1\SHARE\BACKUP' # File system location to write the backup metadata file |
1 |
Connect-AzAccount -TenantId $TenantId $SqlInstance = Connect-DbaInstance -SqlInstance $TargetSQLServer -TrustServerCertificate -NonPooledConnection $vm = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $TargetSQLServer #Reference to our SQL VM in Azure |
Connect to Our Storage Environment in Azure
1 |
$SourceDataDiskName = ($vm.StorageProfile.DataDisks | Where-Object { $_.Name -eq 'Sql1_DataDisk_0' }).Name $SourceLogDiskName = ($vm.StorageProfile.DataDisks | Where-Object { $_.Name -eq 'Sql1_DataDisk_1' }).Name $SourceDataDiskName $SourceLogDiskName Sql1_DataDisk_0 Sql1_DataDisk_1 |
1 |
$SourceDataDisk = Get-AzDisk -ResourceGroupName $ResourceGroupName -DiskName $SourceDataDiskName $SourceLogDisk = Get-AzDisk -ResourceGroupName $ResourceGroupName -DiskName $SourceLogDiskName $SourceDataDisk.Id $SourceLogDisk.Id /subscriptions/fd0c5e48-eea6-4b37-a076-0e23e0df74cb/resourceGroups/Sql1_group/providers/Microsoft.Compute/disks/Sql1_DataDisk_0 /subscriptions/fd0c5e48-eea6-4b37-a076-0e23e0df74cb/resourceGroups/Sql1_group/providers/Microsoft.Compute/disks/Sql1_DataDisk_1 |
Let's Create a Snapshot Config
1 |
$DataSnapshot = New-AzSnapshotConfig ` -SourceUri $SourceDataDisk.Id ` -Location $location ` -CreateOption Copy $LogSnapshot = New-AzSnapshotConfig ` -SourceUri $SourceLogDisk.Id ` -Location $location ` -CreateOption Copy |
Taking a T-SQL-based Snapshot Backup
1 |
$Query = "ALTER DATABASE $DbName SET SUSPEND_FOR_SNAPSHOT_BACKUP = ON" Invoke-DbaQuery -SqlInstance $SqlInstance -Query $Query -Verbose VERBOSE: Database 'Database1' acquired suspend locks in session 64. VERBOSE: I/O is frozen on database Database1. No user action is required. However, if I/O is not resumed promptly, you could cancel the backup. VERBOSE: Database 'Database1' successfully suspended for snapshot backup in session 64. |
1 |
$DataSnapshotName = "Sql1_DataDisk_0$(Get-Date -Format FileDateTime)" $DataSnapshot = New-AzSnapshot ` -Snapshot $DataSnapshot ` -SnapshotName $DataSnapshotName ` -ResourceGroupName $ResourceGroupName $LogSnapshotName = "Sql1_DataDisk_1$(Get-Date -Format FileDateTime)" $LogSnapshot = New-AzSnapshot ` -Snapshot $LogSnapshot ` -SnapshotName $LogSnapshotName ` -ResourceGroupName $ResourceGroupName |
1 |
$BackupFile = "$BackupShare\$DbName-$(Get-Date -Format FileDateTime).bkm" $Query = "BACKUP DATABASE $DbName TO DISK='$BackupFile' WITH METADATA_ONLY, MEDIADESCRIPTION='$($DataSnapshotName.Name)|$($DataSnapshot.Id)'" Invoke-DbaQuery -SqlInstance $SqlInstance -Query $Query -Verbose VERBOSE: I/O was resumed on database Database1. No user action is required. VERBOSE: Database 'Database1' released suspend locks in session 64. VERBOSE: Database 'Database1' originally suspended for snapshot backup in session 64 successfully resumed in session 64. VERBOSE: Processed 0 pages for database 'Database1', file 'Database1' on file 1. VERBOSE: BACKUP DATABASE successfully processed 0 pages in 0.006 seconds (0.000 MB/sec). |
1 |
$LogBackup = Backup-DbaDatabase -SqlInstance $SqlInstance -Database $DbName -Type Log -Path $BackupShare -CompressBackup |
1 |
Get-AzSnapshot -ResourceGroupName $ResourceGroupName | Format-Table ResourceGroupName ManagedBy Sku TimeCreated OsType HyperVGeneration CreationData DiskSizeGB DiskSizeBytes UniqueId --------- ----- -- ------ --- -------- ------ ----- ------- ---- Sql1_group Microsoft.Azure.Management.Compute.Models.SnapshotSku 9/3/2024 12:37:39PM Microsoft.Azure.Management.Compute.Models.CreationData 1024 1099511627776 706e4a9c-896c-46c6-b8f7-04401100b… Sql1_group Microsoft.Azure.Management.Compute.Models.SnapshotSku 9/3/2024 12:37:42PM Microsoft.Azure.Management.Compute.Models.CreationData 1024 1099511627776 18c3bbe1-bb98-4ca3-86e7-e94e6b47f… |
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.
1 |
Get-DbaErrorLog -SqlInstance $SqlInstance -LogNumber 0 | Format-Table Sql1 MSSQLSERVER Sql1 9/3/2024 12:37:32PM spid64 Setting database option suspend_for_snapshot_backup to ON for database 'Database1'. Sql1 MSSQLSERVER Sql1 9/3/2024 12:37:32PM spid64 Database 'Database1' acquired suspend locks in session 64. Sql1 MSSQLSERVER Sql1 9/3/2024 12:37:32PM spid64 I/O is frozen on database Database1. No user action is required. However, if I/O is not resumed promptly, you could cancel the backup. Sql1 MSSQLSERVER Sql1 9/3/2024 12:37:32PM spid64 Database 'Database1' successfully suspended for snapshot backup in session 64. Sql1 MSSQLSERVER Sql1 9/3/2024 12:37:48PM spid64 I/O is frozen on database Database1. No user action is required. However, if I/O is not resumed promptly, you could cancel the backup. Sql1 MSSQLSERVER Sql1 9/3/2024 12:37:48PM spid64 I/O was resumed on database Database1. No user action is required. Sql1 MSSQLSERVER Sql1 9/3/2024 12:37:48PM spid64 Database 'Database1' released suspend locks in session 64. Sql1 MSSQLSERVER Sql1 9/3/2024 12:37:48PM spid64 Database 'Database1' originally suspended for snapshot backup in session 64 successfully resumed in session 64. Sql1 MSSQLSERVER Sql1 9/3/2024 12:37:48PM Backup Database backed up. Database: Database1, creation date(time): 2024/09/03(11:49:49), pages dumped: 66282, first LSN: 39:920:39, last LSN: 39:952:1, number of dump devices: 1,… Sql1 MSSQLSERVER Sql1 9/3/2024 12:37:48PM Backup BACKUP DATABASE successfully processed 0 pages in 0.006 seconds (0.000 MB/sec).… |
1 |
Get-DbaDbBackupHistory -SqlInstance $SqlInstance -Database $DbName -Last SqlInstance Database Type TotalSize DeviceType Start Duration End ------ ---- -- ----- ----- --- ---- -- Sql1 Database1 Full 517.83 MB Disk 2024-09-03 12:37:47.000 00:00:01 2024-09-03 12:37:48.000 |
1 |
Read-DbaBackupHeader -SqlInstance $SqlInstance -Path $BackupFile BackupName : BackupDescription : BackupType : 1 ExpirationDate : Compressed : 0 Position : 1 DeviceType : 2 UserName : aen ServerName : Sql1 DatabaseName : Database1 ... BackupPath : \\FileServer1\SHARE\BACKUP\Database1-20240903T0737464342.bkm BackupSize : 517.83 MB CompressedBackupSize : 517.83 MB |
Read More from This Series
Using T-SQL Snapshot Backup: Are Snapshots Backups?
Using T-SQL Snapshot Backup: Point-in-time Recovery
Using T-SQL Snapshot Backup: Point-in-time Recovery - Azure Edition
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.
1 |
$Query = "ALTER DATABASE $DbName SET OFFLINE WITH ROLLBACK IMMEDIATE" Invoke-DbaQuery -SqlInstance $SqlInstance -Database master -Query $Query |
1 |
Write-Host "Offlining the volume…" -ForegroundColor Red Get-Disk -Number 4 | Set-Disk -IsOffline $True Get-Disk -Number 5 | Set-Disk -IsOffline $True |
1 |
Remove-AzVMDataDisk -VM $vm -Name $SourceDataDiskName Remove-AzVMDataDisk -VM $vm -Name $SourceLogDiskName Update-AzVM -ResourceGroupName $ResourceGroupName -VM $vm |
1 |
$StorageType = 'Premium_LRS' $DataDiskName = 'DATA_CLONE' $DataDiskConfig = New-AzDiskConfig -SkuName $StorageType -Location $location -CreateOption Copy -SourceResourceId $DataSnapshot.Id -Zone 1 $DataDisk = New-AzDisk -ResourceGroupName $ResourceGroupName -DiskName $DataDiskName -Disk $DataDiskConfig $LogDiskName = 'LOG_CLONE' $LogDiskConfig = New-AzDiskConfig -SkuName $StorageType -Location $location -CreateOption Copy -SourceResourceId $LogSnapshot.Id -Zone 1 $LogDisk = New-AzDisk -ResourceGroupName $ResourceGroupName -DiskName $LogDiskName -Disk $LogDiskConfig |
1 |
Add-AzVMDataDisk -Name $DataDiskName -CreateOption Attach -VM $vm -ManagedDiskId $DataDisk.Id -Lun 1 Add-AzVMDataDisk -Name $LogDiskName -CreateOption Attach -VM $vm -ManagedDiskId $LogDisk.Id -Lun 2 Set-AzVMDataDisk -VM $vm -Name 'DATA_CLONE' -Caching ReadWrite Update-AzVM -VM $vm -ResourceGroupName $ResourceGroupName |
1 |
Write-Host "Onlining the volume…" -ForegroundColor Red Get-Disk -Number 4 | Set-Disk -IsOffline $False Get-Disk -Number 5 | Set-Disk -IsOffline $False |
1 |
$Query = "RESTORE DATABASE $DbName FROM DISK = '$BackupFile' WITH METADATA_ONLY, REPLACE, NORECOVERY" Invoke-DbaQuery -SqlInstance $SqlInstance -Database master -Query $Query -Verbose VERBOSE: RESTORE DATABASE successfully processed 0 pages in 0.571 seconds (0.000 MB/sec). |
1 |
Get-DbaDbState -SqlInstance $SqlInstance -Database $DbName Access : MULTI_USER ComputerName : Sql1 DatabaseName : Database1 InstanceName : MSSQLSERVER RW : READ_WRITE SqlInstance : Sql1 Status : RESTORING |
1 |
Restore-DbaDatabase -SqlInstance $SqlInstance ` -Database $DbName ` -Path $LogBackup.BackupPath ` -NoRecovery ` -Continue |
1 |
$Query = "RESTORE DATABASE $DbName WITH RECOVERY" Invoke-DbaQuery -SqlInstance $SqlInstance -Database master -Query $Query -Verbose VERBOSE: RESTORE DATABASE successfully processed 0 pages in 1.596 seconds (0.000 MB/sec). |
1 |
Get-DbaDbState -SqlInstance $SqlInstance -Database 'Database1' Access : MULTI_USER ComputerName : SqlServer1 DatabaseName : Database1 InstanceName : MSSQLSERVER RW : READ_WRITE SqlInstance : Sql1 Status : 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.
Cyber Resilience & Risk Reduction
Boost cyber resilience and reduce risks with solutions that protect your organization from threats, ensure data recovery, and maintain business continuity.