Recovering SQL Server Databases with Veeam: A Step-by-Step Guide for vSphere Environments
SQL Server recovery in Veeam is one of those areas where you really need to know which backup path you are on before you start. Veeam gives you two completely different backup engines for SQL Server, and they do not behave the same way at restore time -- different cmdlets, different mechanics, different feature sets. Getting that wrong before you kick off a restore is a frustrating way to spend a maintenance window. This guide covers all four recovery paths -- restore to original location, restore to custom location, individual table restore, and export to file -- plus Instant Recovery, across both backup types. Everything is based on VBR 12 and later.
First: Which Backup Type Are You Working With?
Answer this before you touch anything else. The two paths split hard at restore time, and mixing up cmdlets or workflows between them is one of the most reliable ways to make a SQL restore fail in a way that does not give you a useful error message.
Application-aware image backup is the VM snapshot path. VBR takes a VSS-consistent snapshot of the VM, and with application-aware processing enabled, it ships transaction logs to the repository on a schedule you set. At restore time, Veeam Explorer mounts the backup to C:\VeeamFLR on the target, deploys a short-lived Veeam SQL Restore Service, copies the database files and log backups from that mount to the native filesystem, starts the database, then cleans up the mount and removes the service. The staging server only comes into play if you need to restore to a specific transaction.
Veeam Plug-in for Microsoft SQL Server is a native SQL Server backup -- no VM snapshots involved. It integrates directly with SQL Server's backup APIs and ships data straight to the Veeam repository. At restore time, the plug-in creates a VDI device on the target -- a virtual device that presents itself as backup storage to SQL Server -- and Veeam Data Movers stream the data from the repository directly into that device. No file copy to C:\VeeamFLR, no mount, no staging. The restore component on the target drives everything. It is a fundamentally different operation.
Here is the quick reference for what each path supports:
| Capability | Image-based backup | Plug-in backup |
|---|---|---|
| Restore to original location | Supported | Supported |
| Restore to custom location / rename | Supported | Supported |
| Point-in-time restore (log replay) | Supported | Supported |
| Restore to specific transaction | Image only | Not available |
| Table / schema restore | Image only | Not available |
| Export database to file | Supported | Not available |
| Instant Recovery (publish from backup) | Supported | Not available |
| Requires staging server | Only for transaction-level restore | Never |
| Requires ADMIN$ share on target | Yes (or Veeam Installer Service pre-deployed on the target) | No |
Image-based restores use Start-VESQLRestoreSession and Restore-VESQLDatabase. Plug-in restores use Start-VESQLPluginRestoreSession and Start-VESQLPluginDatabaseRestore. Using the wrong set against the wrong backup type will either fail immediately or return zero results without a meaningful error. Know which you have before opening a session.
Prerequisites
| Requirement | Details |
|---|---|
| VBR version | Version 12 or later. Veeam Plug-in for Microsoft SQL Server managed mode (VBR-deployed) requires VBR 12. |
| SQL Server permissions | The account used for the restore must be a member of the sysadmin fixed server role on the target SQL instance. A lower-privilege account will fail during the pre-restore validation checks. |
| ADMIN$ share (image-based path) | Veeam Explorer deploys the Veeam SQL Restore Service via the administrative share. If ADMIN$ is blocked by policy, you must pre-deploy the Veeam Installer Service on the target instead -- Veeam will then use it to check for and install the persistent components (Veeam SQL Agent Service and Veeam Log Shipping Service) it needs. Without one of these two paths available, the restore will not proceed. |
| Staging server (transaction-level restore) | Required only when restoring to a specific transaction using the image-based path. VBR ships with a local SQL Server instance that Veeam uses as the default staging server -- you do not need to configure anything if that default is sufficient. To use a different instance, open Explorer, click the main menu, and go to Options. The staging server must be a separate SQL instance from both the source and the restore target. |
| Veeam Plug-in for Microsoft SQL Server | Required only for the plug-in backup path. Must be installed on the SQL Server host and version-matched to the VBR server. The plug-in is available from the Veeam ISO or the Veeam downloads page under Plugins for Enterprise Applications. |
| Application-aware backup configured | For the image-based path: the backup job must have application-aware processing enabled, and transaction log backup must be configured in the job settings if you need log-level recovery granularity. |
| Target SQL instance online | For all restore paths: the SQL Server service must be running on the target host before Explorer can connect and validate the restore environment. |
Restore to Original Location
This is your primary break-fix path. The database goes back to the same SQL instance it came from. Veeam takes it offline, restores the data files and applies the transaction logs, then brings it back online. The rest of the SQL instance stays up -- only the database being restored is affected.
▶ GUI -- Image-based backup- In the VBR console, go to Home > Backups, find the job covering the SQL VM, right-click the restore point, and select Restore application items > Microsoft SQL Server databases. Veeam Explorer for Microsoft SQL Server opens.
- Expand the SQL instance in the left pane to see the available databases. Give it a moment to populate -- the tree pulls metadata from the mounted backup.
- Right-click the target database and select Restore database > To the original location.
- On the Restore point page, choose your recovery target: restore point only (no log replay), point in time (log replay to a specific moment), or a specific transaction (requires staging server). For point-in-time, use the date and time picker to set your target.
- If prompted for credentials, provide an account with sysadmin rights on the target SQL instance.
- Review the summary and click Restore. Watch the task log at the bottom of Explorer for progress. You will see the database go offline, files restore, logs apply, and the database come back online.
Restore to original location -- point-in-time selection with log replay options visible in the restore wizard.
The plug-in restore path launches the same Veeam Explorer interface but reaches it differently -- via the plug-in backups node rather than the VM backup jobs.
- In the VBR console, go to Home > Backups > Applications (or Plug-in backups depending on your VBR version). Locate the plug-in backup for the SQL host.
- Right-click the backup and select Restore application items > Microsoft SQL Server databases. Veeam Explorer opens with the plug-in backup loaded.
- Right-click the database and select Restore database > To the original location.
- Select the restore point. Note that with plug-in backups you can restore to the latest state or to a point in time, but not to a specific transaction -- that option is only available from image-based backups.
- Click Restore and monitor the task log.
Import-Module Veeam.Backup.PowerShell
# Get the VM backup and its most recent restore point
$backup = Get-VBRBackup -Name "SQL-VM-Backup"
$restorePoint = Get-VBRRestorePoint -Backup $backup -Name "sql-vm-hostname" |
Sort-Object CreationTime -Descending | Select-Object -First 1
# Start a VESQL restore session against that restore point
$session = Start-VESQLRestoreSession -RestorePoint $restorePoint
# Enumerate databases in the session and pick the one you want
$db = Get-VESQLDatabase -Session $session -Name "YourDatabase"
# Restore to original location -- latest state
Restore-VESQLDatabase -Database $db -RestoreToOriginalLocation
# To restore to a specific point in time instead:
# Restore-VESQLDatabase -Database $db -RestoreToOriginalLocation `
# -RestoreToPointInTime (Get-Date "2024-11-01 03:45:00")
# Close the session when done
Stop-VESQLRestoreSession -Session $session
Import-Module Veeam.Backup.PowerShell
# Get the plug-in backup for the SQL host
$pluginBackup = Get-VESQLPluginBackup -Name "sql-host.example.com"
# Start a plug-in restore session
$session = Start-VESQLPluginRestoreSession -Backup $pluginBackup
# Enumerate available databases
$db = Get-VESQLPluginDatabase -Session $session -Name "YourDatabase"
# Check the available restore interval for this database
Get-VESQLPluginLogInterval -Database $db
# Kick off the restore -- this is async, poll for status
$restore = Start-VESQLPluginDatabaseRestore -Database $db -RestoreToOriginalLocation
# Poll until complete
do {
Start-Sleep -Seconds 10
$status = Get-VESQLPluginDatabaseRestore -Restore $restore
Write-Host "Status: $($status.State)"
} while ($status.State -notin @("Success","Failed"))
Stop-VESQLPluginRestoreSession -Session $session
Unlike image-based restores which block until completion, Start-VESQLPluginDatabaseRestore returns immediately and the restore runs in the background. You have to poll Get-VESQLPluginDatabaseRestore to track progress and detect completion or failure. Build that loop into any automation scripts or you will have no idea if the restore actually succeeded.
Restore to Custom Location
Use this when you need the database somewhere other than where it came from -- a different SQL instance, a different server, or under a different database name. This is your dev/test refresh path, your pre-production validation path, and your cross-environment migration path all in one.
▶ GUI -- Image-based backup- Launch Veeam Explorer as in Path 1, steps 1 and 2.
- Right-click the target database and select Restore database > To a different location.
- On the Target server page, click Add and enter the destination SQL Server hostname or IP. Veeam will test connectivity and verify the SQL instance is reachable.
- Set the Target database name. If you are restoring to the same instance under a new name, this prevents a collision with the existing database. If restoring to a completely different server, you can keep the original name.
- Set the Target database files path -- this is where the MDF and LDF files will land on the destination server. The path must already exist on the target.
- Select your recovery scope (restore point, point-in-time, or specific transaction) and provide sysadmin credentials for the destination instance.
- Review the summary and click Restore.
Custom location restore -- setting the destination SQL instance, new database name, and target file path.
Veeam recommends installing the VBR console (and therefore running Explorer) directly on the SQL Server host when possible for custom location restores. When Explorer runs on the same machine as the target SQL instance, it skips deploying the Veeam SQL Restore Service because the console is already there -- which removes one potential point of failure, especially if ADMIN$ is restricted in your environment.
Import-Module Veeam.Backup.PowerShell
$backup = Get-VBRBackup -Name "SQL-VM-Backup"
$restorePoint = Get-VBRRestorePoint -Backup $backup -Name "sql-vm-hostname" |
Sort-Object CreationTime -Descending | Select-Object -First 1
$session = Start-VESQLRestoreSession -RestorePoint $restorePoint
$db = Get-VESQLDatabase -Session $session -Name "YourDatabase"
# Restore to a different SQL instance under a new name
# -ServerName : destination SQL Server host
# -InstanceName : SQL instance name (use MSSQLSERVER for default instance)
# -DatabaseName : new name for the restored database
# -DatabaseLocation : path on the target server where data files will land
Restore-VESQLDatabase `
-Database $db `
-ServerName "sql-dest.example.com" `
-InstanceName "MSSQLSERVER" `
-DatabaseName "YourDatabase_Restore" `
-DatabaseLocation "D:\SQLData\YourDatabase_Restore" `
-RestoreToPointInTime (Get-Date "2024-11-01 03:45:00")
Stop-VESQLRestoreSession -Session $session
Import-Module Veeam.Backup.PowerShell
$pluginBackup = Get-VESQLPluginBackup -Name "sql-host.example.com"
$session = Start-VESQLPluginRestoreSession -Backup $pluginBackup
$db = Get-VESQLPluginDatabase -Session $session -Name "YourDatabase"
$restore = Start-VESQLPluginDatabaseRestore `
-Database $db `
-ServerName "sql-dest.example.com" `
-InstanceName "MSSQLSERVER" `
-DatabaseName "YourDatabase_Restore" `
-DatabaseLocation "D:\SQLData\YourDatabase_Restore"
do {
Start-Sleep -Seconds 10
$status = Get-VESQLPluginDatabaseRestore -Restore $restore
Write-Host "Status: $($status.State)"
} while ($status.State -notin @("Success","Failed"))
Stop-VESQLPluginRestoreSession -Session $session
Restore Individual Tables (Staged Restore)
This one is image-based only -- there is no equivalent in the plug-in path. It is also the most nuanced of the four paths, because it requires a staging SQL Server and has more moving parts than a straight database restore. That said, it is genuinely useful when someone drops or corrupts a table and you need just that object back without overwriting the whole production database.
What Veeam does here: it mounts the backup, restores the entire database to the staging server (including log replay to your target transaction if needed), lets you browse and select the tables or schema objects you want, then copies just those objects back to the production server -- either overwriting what is there or restoring them under a different name so you can compare. The staging server handles all the log replay work in isolation so production is never exposed to a partial restore state.
VBR installs a local SQL Server instance that Veeam uses as a staging server by default, so you may already have one configured without knowing it. To restore to a specific transaction (not just a point in time), that staging server must be reachable and must be a different SQL instance from both the source and the target. If you want to use a different instance, open Explorer's main menu and go to Options to change it. Without a working staging server, the specific transaction option will be greyed out.
- Launch Veeam Explorer from the VBR console using an image-based restore point as in Path 1, steps 1 and 2.
- Right-click the target database and select Restore database schema and data.
- On the Restore point page, set your recovery target -- restore point, point in time, or specific transaction. For specific transaction, Veeam will replay logs on the staging server and show you each transaction in a browsable list.
- On the Target server page, specify the destination SQL instance where you want the recovered objects to land. This can be the original production instance.
- On the Database objects page, expand the database tree and select the specific tables or schema objects to restore. You can select individual tables, entire schemas, or the full database object tree.
- On the Names for restored objects page, choose whether to restore objects with their original names (which will overwrite existing objects) or add a prefix or suffix so the restored objects land alongside the originals for comparison.
- Complete the wizard and click Restore. Veeam will restore the full database to the staging server, extract the selected objects, and transfer them to the target instance.
Staged table restore -- browsing the database schema and selecting individual tables for recovery to the production instance.
Table and schema restore through Veeam Explorer does not have a dedicated PowerShell cmdlet path. The Restore-VESQLDatabase cmdlet restores at the database level only. If you need to script table-level recovery, your options are: use the GUI, or restore the full database to a staging instance via PowerShell and then use native SQL Server tooling (SELECT INTO, SSMS import/export, or BACPAC) to extract and transfer the specific objects you need.
Export Database to File
Export gives you a copy of the database as native SQL Server backup files (.bak) that you can take anywhere -- another environment, an isolated network, a different team. No live SQL instance required at the destination. This path is image-based only.
▶ GUI -- Image-based backup only- Launch Veeam Explorer from an image-based restore point as in Path 1, steps 1 and 2.
- Right-click the target database and select Export database.
- Specify the destination folder. This can be a local path on the machine running VBR or Explorer, or a UNC path to a network share. Make sure there is enough space for the full database backup plus transaction logs.
- Set the recovery scope: restore point, point in time, or specific transaction.
- Click Export. Veeam will restore the database to the export path as a standard SQL Server backup set (.bak files). These files can be restored using native SQL Server
RESTORE DATABASEcommands or SSMS on any compatible SQL Server instance.
Import-Module Veeam.Backup.PowerShell
$backup = Get-VBRBackup -Name "SQL-VM-Backup"
$restorePoint = Get-VBRRestorePoint -Backup $backup -Name "sql-vm-hostname" |
Sort-Object CreationTime -Descending | Select-Object -First 1
$session = Start-VESQLRestoreSession -RestorePoint $restorePoint
$db = Get-VESQLDatabase -Session $session -Name "YourDatabase"
# Export as a native SQL Server .bak file set
# The destination folder will be created if it does not exist
Export-VESQLDatabase `
-Database $db `
-Path "D:\SQLExports\YourDatabase_20241101" `
-RestoreToPointInTime (Get-Date "2024-11-01 03:45:00")
# To export to latest state, omit -RestoreToPointInTime entirely
Stop-VESQLRestoreSession -Session $session
The exported files are standard SQL Server backup sets. To restore on another instance: RESTORE DATABASE YourDatabase FROM DISK = 'D:\SQLExports\YourDatabase_20241101\YourDatabase.bak' WITH NORECOVERY; followed by RESTORE LOG for each transaction log file in the export folder, finishing with RESTORE DATABASE YourDatabase WITH RECOVERY;. Or use SSMS Restore wizard and point it at the folder -- it will auto-detect the backup set.
Instant Recovery (Publish Database from Backup)
Instant Recovery for SQL is different from all four paths above. Instead of copying data to a target server and starting the database there, Veeam mounts the backup via iSCSI and attaches the database directly to a SQL instance -- the database is available within seconds, running live from the repository. This is your fastest path to RTO: the application is back up immediately while a full data migration runs in the background, or you can use it purely as a validation tool to confirm what is actually in a backup before committing to a production restore.
The tradeoff is real: performance is constrained by repository connection speed, and any writes go to a cache on the mount server while the background copy catches up. It is not a permanent solution. Treat it as a bridge -- get the application online, then finish the switchover to local storage or unpublish and move on. Do not leave databases running from the repository for extended periods.
▶ GUI -- Image-based backup only- Launch Veeam Explorer from an image-based restore point.
- Right-click the target database and select Publish database.
- Specify the target SQL Server instance where the database will be attached. This can be the production instance or a separate validation host.
- Set a target database name for the published copy -- something distinct from the production database name if you are attaching to the same instance.
- Select the recovery scope and click Publish. The database will be attached and available within seconds -- no data copy required.
- When ready to switch over to production storage, right-click the published database in Explorer and select Switch to production. Veeam will migrate the files in the background and detach from the repository when done. To discard without switching over, select Unpublish.
This is the one place where you do not need to babysit the session. Once Instant Recovery is started, the Veeam Explorers Recovery Service on the mount server takes ownership -- you can close Veeam Explorer and reopen it later to check status, perform switchover, or unpublish. The iSCSI mount and write cache remain active on the mount server independently. This is different from a standard restore session, which does require Explorer to stay connected.
Import-Module Veeam.Backup.PowerShell
$backup = Get-VBRBackup -Name "SQL-VM-Backup"
$restorePoint = Get-VBRRestorePoint -Backup $backup -Name "sql-vm-hostname" |
Sort-Object CreationTime -Descending | Select-Object -First 1
$session = Start-VESQLRestoreSession -RestorePoint $restorePoint
$db = Get-VESQLDatabase -Session $session -Name "YourDatabase"
# Publish the database -- attaches it to the target SQL instance directly from backup
Publish-VESQLDatabase `
-Database $db `
-ServerName "sql-prod.example.com" `
-InstanceName "MSSQLSERVER" `
-DatabaseName "YourDatabase_Published"
# Check published database state
$published = Get-VESQLPublishedDatabase -Session $session
Write-Host "Published DB state: $($published.State)"
# --- When ready to migrate to production storage ---
# Build switchover options and switch over
$switchOptions = New-VESQLIRSwitchOverOptions `
-DatabaseLocation "D:\SQLData\YourDatabase"
Switch-VESQLIRDatabase `
-Database (Get-VESQLIRDatabase -Session $session -Name "YourDatabase_Published") `
-SwitchOverOptions $switchOptions
# --- OR, to discard without switching ---
Unpublish-VESQLDatabase -Database $published
Stop-VESQLRestoreSession -Session $session
Post-Recovery Verification
Run these checks after any restore path before handing the database back to application teams. A restore that completes without errors is a good start -- it is not the same as a database that is actually healthy.
Confirm the Database is Online
-- Check database state and recovery model
SELECT
name,
state_desc,
recovery_model_desc,
log_reuse_wait_desc
FROM sys.databases
WHERE name = 'YourDatabase';
-- You want:
-- state_desc = ONLINE
-- recovery_model_desc = FULL (if it was FULL before restore)
-- If state_desc shows RESTORING, the restore did not complete correctly
Verify the Recovery Point
-- Confirm the last restore time and the recovery stop point
SELECT
restore_date,
destination_database_name,
user_name,
backup_finish_date,
restore_type
FROM msdb.dbo.restorehistory
WHERE destination_database_name = 'YourDatabase'
ORDER BY restore_date DESC;
Check the SQL Server Error Log
-- Scan the current error log for anything that looks wrong post-restore
EXEC sp_readerrorlog 0, 1, 'YourDatabase';
-- A clean restore ends with a line similar to:
-- "Recovery completed for database YourDatabase"
-- No errors referencing the database after that line is what you want
Run DBCC CHECKDB
-- Run a full integrity check -- worth the time before going back into production
-- On large databases, run with NO_INFOMSGS and PHYSICAL_ONLY first for speed
DBCC CHECKDB ('YourDatabase') WITH NO_INFOMSGS;
-- Zero errors reported = you are good
-- If CHECKDB returns errors, do not put the database into production service
-- until you understand and resolve what it found
After a restore, SQL Server breaks the log backup chain. Your first post-restore action after confirming the database is healthy should be a full database backup -- this re-establishes the chain so subsequent log backups are valid. If you skip this and only run differential or log backups, you will not have a usable chain if you need to recover again.
What You've Completed
- Understood the two distinct SQL backup paths in Veeam and why they use different cmdlet namespaces, different restore mechanics, and have different feature sets at recovery time.
- Reviewed the decision matrix for which features are available on each path -- table restore, export, and Instant Recovery are image-based only; plug-in restores are async and have no staging server dependency.
- Completed Path 1 -- restore to original location -- via GUI and PowerShell for both image-based and plug-in backups, including point-in-time options and the async polling pattern for plug-in restores.
- Completed Path 2 -- restore to a different SQL instance or under a new name -- via GUI and PowerShell for both backup types.
- Completed Path 3 -- individual table and schema restore via staged restore, including staging server requirements, the object selection workflow, and why there is no PowerShell equivalent for table-level recovery.
- Completed Path 4 -- export database to native .bak files for handoff or offline use, including how to restore the exported files on a receiving SQL instance.
- Walked through Instant Recovery -- publishing a database directly from backup, the Explorer session lifecycle requirement, and the switchover vs. unpublish options.
- Ran post-recovery verification: database state, restore history, error log review, and DBCC CHECKDB -- plus re-establishing the log backup chain after restore.