Press "Enter" to skip to content

Automating SQL Server Live Mounts with Rubrik Alta (4.0)

Joshua Stenhouse 3

How many times in your career have you tested something that totally blew you away? Your mind racing with use cases both past and present. The first VM you created? Check. Your first vMotion? Check. Your first storage vMotion? Check. But what next? I just found one to add to my list and its SQL Server Live Mounts in Rubrik Alta (4.0). So what exactly is it and why is it so amazing? Glad you asked, read on!

Think about your backups today. Isn’t it a bit like having an insurance policy that constantly needs you to administer it, without giving you anything back unless you need to make a claim? Even then, it doesn’t make it easy! What if you could have the insurance, set it and forget it, all while giving you something amazing back on a daily basis? That is what SQL Server Live Mounts in Rubrik Alta (4.0) does.

Rather than just taking backups of your SQL databases, with Rubrik you can now instantly mount read/write copies of your SQL databases directly on the Rubrik appliance to any SQL host or instance in your environment. Rubrik uses SMBv3 and UNC paths to perform the DB mount along with handling the transaction logs for specific point in time recovery. All done in less than 1 minute with no production storage usage and no impact to your production databases. Wow.

This means that Rubrik can now automatically give you a copy of all your production databases for DBCC checks, reporting and dev/test use cases on the same or a secondary instance with 30k IOPS per Rubrik appliance. You can do this using self-service RBAC in the Rubrik GUI, or you can automate the process end to end using the REST APIs. With the scripts I will share with you in this post, you can have the last backup of your SQL DBs automatically mounted every morning without having to lift a finger (that is of course, after configuring the script). Excited? You should be.

If you want to hit the ground running you can simply download the example scripts (one for mounting and another for unmounting) here:

RubrikSQLBulkLiveMountsv2.zip

The first thing we need is a CSV list of the DB live mounts we want to perform. I added an example to the zip file above, or you can roll your own with the following columns:

SourceSQLHostName,SourceInstanceName,SourceDatabaseName,TargetSQLHostName,TargetInstanceName,TargetDatabaseName

Hopefully, I made the columns self-explanatory. You only need 1 SQL database protected to test, as you can simply mount multiple copies of the same DB on the same host so long as each has a different name. For a production use case, I would expect you to use multiple DBs mounted to different hosts/instances.

With your CSV created, edit the variables at the start and run the below script to automatically mount your SQL DBs! I’d like to thank Peter Milanese (Rubrik’s DevOps Guru) for his help on the weekend with the correct formatting of time stamp required in the JSON (totally stumped me):

################################################
# Configure the variables below for the Rubrik Cluster
################################################
$RubrikCluster = "192.168.0.200"
$SQLLiveMountCSV = "C:\Scripts\RubrikSQLLiveMountsv1\RubrikSQLLiveMounts.csv"
$LogDirectory = "C:\Scripts\RubrikSQLLiveMountsv1"
# Username and password to authenicate with Rubrik API
$RubrikUser = "admin" 
$RubrikPassword = "Password123!"
########################################################################################################################
# Nothing to configure below this line - Starting the main function of the script
########################################################################################################################
# Adding certificate exception to prevent API errors
################################################
add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
################################################
# Starting logging & importing the CSV
################################################
$Now = get-date
$Log = $LogDirectory + "\Rubrik-SQLLiveMountLog-" + $Now.ToString("yyyy-MM-dd") + "@" + $Now.ToString("HH-mm-ss") + ".log"
Start-Transcript -Path $Log -NoClobber 
$SQLiveMounts = import-csv $SQLLiveMountCSV
################################################
# Building Rubrik API string & invoking REST API
################################################
$baseURL = "https://" + $RubrikCluster + "/api/v1/"
$xRubrikSessionURL = $baseURL + "session"
$authInfo = ("{0}:{1}" -f $RubrikUser,$RubrikPassword)
$authInfo = [System.Text.Encoding]::UTF8.GetBytes($authInfo)
$authInfo = [System.Convert]::ToBase64String($authInfo)
$headers = @{Authorization=("Basic {0}" -f $authInfo)}
$TypeJSON = "application/json"
# Authentication with API
Try 
{
$xRubrikSessionResponse = Invoke-WebRequest -Uri $xRubrikSessionURL -Headers $headers -Method POST -Body $sessionBody -ContentType $TypeJSON
}
Catch 
{
Write-Host $_.Exception.ToString()
$error[0] | Format-List -Force
}
# Extracting the token from the JSON response
$xRubrikSession = (ConvertFrom-Json -InputObject $xRubrikSessionResponse.Content)
$RubrikSessionHeader = @{'Authorization' = "Bearer $($xRubrikSession.token)"}
###############################################
# Getting list of SQL Databases
###############################################
$SQLDBListURL = $baseURL+"mssql/db?limit=5000"
Try 
{
$SQLDBListJSON = Invoke-RestMethod -Uri $SQLDBListURL -TimeoutSec 100 -Headers $RubrikSessionHeader -ContentType $TypeJSON
$SQLDBList = $SQLDBListJSON.data
}
Catch 
{
Write-Host $_.Exception.ToString()
$error[0] | Format-List -Force
}
###############################################
# Getting list of SQL Instances
###############################################
$SQLInstanceListURL = $baseURL+"mssql/instance?limit=5000"
Try 
{
$SQLInstanceJSON = Invoke-RestMethod -Uri $SQLInstanceListURL -TimeoutSec 100 -Headers $RubrikSessionHeader -ContentType $TypeJSON
$SQLInstanceList = $SQLInstanceJSON.data
}
Catch 
{
Write-Host $_.Exception.ToString()
$error[0] | Format-List -Force
}
###############################################
# Building a list of SQL instances by hostname, needed to enable selection of the correct instance
###############################################
$SQLInstanceArray = @()
ForEach ($SQLInstance in $SQLInstanceList)
{
$SQLInstanceName = $SQLInstance.name
$SQLInstanceID = $SQLInstance.id
$SQLInstanceHostName = $SQLInstance.rootProperties.rootName
$SQLInstanceHostID = $SQLInstance.rootProperties.rootId
# Getting DBs for each instance, to aid with troubleshooting
$SQLInstanceDBs = $SQLDBList | Where-Object {$_.instanceID -eq $SQLInstanceID} | Select -ExpandProperty Name
$SQLInstanceDBCount = $SQLInstanceDBs.Count
# Adding to array
$SQLInstanceArrayLine = new-object PSObject
$SQLInstanceArrayLine | Add-Member -MemberType NoteProperty -Name "InstanceName" -Value "$SQLInstanceName"
$SQLInstanceArrayLine | Add-Member -MemberType NoteProperty -Name "InstanceID" -Value "$SQLInstanceID"
$SQLInstanceArrayLine | Add-Member -MemberType NoteProperty -Name "HostName" -Value "$SQLInstanceHostName"
$SQLInstanceArrayLine | Add-Member -MemberType NoteProperty -Name "HostNameID" -Value "$SQLInstanceHostID"
$SQLInstanceArrayLine | Add-Member -MemberType NoteProperty -Name "DBCount" -Value "$SQLInstanceDBCount"
$SQLInstanceArrayLine | Add-Member -MemberType NoteProperty -Name "DBs" -Value "$SQLInstanceDBs"
$SQLInstanceArray += $SQLInstanceArrayLine
}
"SQLInstancesFound:"
$SQLInstanceArray | Format-Table -AutoSize
###############################################
# Getting list of Hosts - Needed to ensure target host is registered
###############################################
$WindowsHostsURL = $baseURL+"host?limit=5000"
Try 
{
$WindowsHostsJSON = Invoke-RestMethod -Uri $WindowsHostsURL -TimeoutSec 100 -Headers $RubrikSessionHeader -ContentType $TypeJSON
$WindowsHosts = $WindowsHostsJSON.data
}
Catch 
{
Write-Host $_.Exception.ToString()
$error[0] | Format-List -Force
}
###############################################
# Start For Each SQL DB below
###############################################
ForEach ($SQLiveMount in $SQLiveMounts)
{
# Setting variables
$SourceSQLHostName = $SQLiveMount.SourceSQLHostName
$SourceInstanceName = $SQLiveMount.SourceInstanceName
$SourceDatabaseName = $SQLiveMount.SourceDatabaseName
$TargetSQLHostName = $SQLiveMount.TargetSQLHostName
$TargetInstanceName = $SQLiveMount.TargetInstanceName
$TargetDatabaseName = $SQLiveMount.TargetDatabaseName
# Incrementing TargetDatabaseName if misconfigured to match SourceDatabaseName on the same instance and host
IF (($SourceSQLHostName -eq $TargetSQLHostName) -AND ($SourceInstanceName -eq $TargetInstanceName) -AND ($SourceDatabaseName -eq $TargetDatabaseName))
{
$TargetDatabaseName = $TargetDatabaseName + " 1"
}
# Inserting space in log for readability
"--------------------------------------------"
"Performing Live Mount For:
DB:$SourceDatabaseName Instance:$SourceInstanceName Host:$SourceSQLHostName
To
DB:$TargetDatabaseName Instance:$TargetInstanceName Host:$TargetSQLHostName"
###############################################
# Checking values exist in Rubrik system, if any are not found then the live mount cannot run
###############################################
$SourceSQLHostNameCheck = $WindowsHosts | Where-Object {$_.hostname -contains $SourceSQLHostName}
$SourceInstanceNameCheck = $SQLInstanceArray | Where-Object {(($_.HostName -eq $SourceSQLHostName) -AND ($_.InstanceName -eq $SourceInstanceName))}
$SourceDatabaseNameCheck = $SQLDBList | Where-Object {(($_.instanceName -eq $SourceInstanceName) -AND ($_.name -eq $SourceDatabaseName))}
$TargetSQLHostNameCheck = $WindowsHosts | Where-Object {$_.hostname -eq $TargetSQLHostName}
$TargetInstanceNameCheck = $SQLInstanceArray | Where-Object {(($_.HostName -eq $TargetSQLHostName) -AND ($_.InstanceName -eq $TargetInstanceName))}
# Output of results
"SourceSQLHostNameCheck:"
IF ($SourceSQLHostNameCheck) {"PASS"} ELSE {"FAIL - SQLHostName Not Found"} 
"SourceInstanceNameCheck:"
IF ($SourceInstanceNameCheck) {"PASS"} ELSE {"FAIL - InstanceName Not Found"} 
"SourceDatabaseNameCheck:"
IF ($SourceDatabaseNameCheck) {"PASS"} ELSE {"FAIL - DatabaseName Not Found"} 
"TargetSQLHostNameCheck:"
IF ($TargetSQLHostNameCheck) {"PASS"} ELSE {"FAIL - SQLHostName Not Found"} 
"TargetInstanceNameCheck:"
IF ($TargetInstanceNameCheck) {"PASS"} ELSE {"FAIL - InstanceName Not Found"} 
###############################################
# IF statement to bypass Live Mount command if all tests variables are not null
###############################################
IF (($SourceSQLHostNameCheck) -AND ($SourceInstanceNameCheck) -AND ($SourceDatabaseNameCheck) -AND ($TargetSQLHostNameCheck) -AND ($TargetInstanceNameCheck))
{
# All tests have a value are therfore the live mount can proceed
###############################################
# Selecting the SourceInstanceID, SourceDatabaseID & TargetInstanceID for the API call
###############################################
$SourceInstanceID = $SQLInstanceArray | Where-Object {(($_.HostName -eq $SourceSQLHostName) -AND ($_.InstanceName -eq $SourceInstanceName))} | Select -ExpandProperty InstanceID -First 1
"SourceInstanceID:$SourceInstanceID"
$SourceDatabaseID = $SQLDBList | Where-Object {(($_.instanceID -eq $SourceInstanceID) -AND ($_.name -eq $SourceDatabaseName))} | Select -ExpandProperty id
"SourceDatabaseID:$SourceDatabaseID"
$TargetInstanceID = $SQLInstanceArray | Where-Object {(($_.HostName -eq $TargetSQLHostName) -AND ($_.InstanceName -eq $TargetInstanceName))} | Select -ExpandProperty InstanceID -First 1
"TargetInstanceID:$TargetInstanceID"
###############################################
# Getting the most recent SQL DB Snapshot
###############################################
$SQLDBSnapshotURL = $baseURL+"mssql/db/"+$SourceDatabaseID+"/snapshot"
Try 
{
$SQLDBSnapshotJSON = Invoke-RestMethod -Uri $SQLDBSnapshotURL -TimeoutSec 100 -Headers $RubrikSessionHeader -ContentType $TypeJSON
$SQLDBSnapshots = $SQLDBSnapshotJSON.data
}
Catch 
{
Write-Host $_.Exception.ToString()
$error[0] | Format-List -Force
}
# Selecting most recent snapshot
$SQLDBSnapshotDate = $SQLDBSnapshots | Sort-Object Date -Descending | Select -ExpandProperty date -First 1
"Using Snapshot:$SQLDBSnapshotDate"
#  POSIX/ms format conversion from snapshot date time for POST to API - thanks to Peter Milanese @ Rubrik for supplying this 
$SQLDBSnapshotTimeStampMS = (Get-Date (Get-Date -Date ([DateTime]::Parse($SQLDBSnapshotDate)).ToUniversalTime()) -UFormat %s) + "000"
"SQLDBSnapshotTimeStampMS:$SQLDBSnapshotTimeStampMS"
###########################################
# Create JSON then POST to Live Mount REST API URL 
###########################################
# Creating POST URL
$SQLDBLiveMountURL = $baseURL+"mssql/db/"+$SourceDatabaseID+"/mount"
# Creating JSON for POST
$SQLDBLiveMountJSON =
"{
""recoveryPoint"":
        {
       ""timestampMs"":$SQLDBSnapshotTimeStampMS
        },
""targetInstanceId"": ""$TargetInstanceID"",
""mountedDatabaseName"": ""$TargetDatabaseName""
}"
# POST to API
Try 
{
$SQLDBLiveMountPOST = Invoke-RestMethod -Method Post -Uri $SQLDBLiveMountURL -Body $SQLDBLiveMountJSON -TimeoutSec 100 -Headers $RubrikSessionHeader -ContentType $TypeJSON
$SQLDBLiveMountSuccess = $TRUE
}
Catch 
{
$SQLDBLiveMountSuccess = $FALSE
Write-Host $_.Exception.ToString()
$error[0] | Format-List -Force
}
"SQLDBLiveMountSuccess:$SQLDBLiveMountSuccess"
# End of IF statement to run live mounts below
}
# End of IF statement to run live mounts above
ELSE
{
"Skipping Live Mount for DB:$SourceDatabaseName Instance:$SourceInstanceName Host:$SourceSQLHostName
Misconfigured, one or more elements were not found in Rubrik to perform the operation."
}
# End of for each SQL DB below
}
# End of for each SQL DB above
# Inserting space in log for readability
"--------------------------------------------"
"End of LiveMount Script"
################################################
# Stopping logging
################################################
Stop-Transcript
###############################################
# End of script
###############################################

How amazing was that? You can see I now have 2 copies of my DB mounted directly from my Rubrik appliance:

I added multiple host outputs along with some tests and transcript logging to help you troubleshoot any issues. Schedule your mount script to run daily at 7am and you are good to go, but we don’t want 1000s of live mounts for obvious reasons and we can’t mount the same DB name to an instance if it already exists (a SQL server limitation). So, the next thing we need to do is configure and schedule the unmount script below which uses the same CSV to automatically unmount the live mounts you just created:

################################################
# Configure the variables below for the Rubrik Cluster
################################################
$RubrikCluster = "192.168.0.200"
$SQLLiveMountCSV = "C:\Scripts\RubrikSQLLiveMountsv1\RubrikSQLLiveMounts.csv"
$LogDirectory = "C:\Scripts\RubrikSQLLiveMountsv1"
# Username and password to authenicate with Rubrik API
$RubrikUser = "admin" 
$RubrikPassword = "Password123!"
########################################################################################################################
# Nothing to configure below this line - Starting the main function of the script
########################################################################################################################
# Adding certificate exception to prevent API errors
################################################
add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
################################################
# Starting logging & importing the CSV
################################################
$Now = get-date
$Log = $LogDirectory + "\Rubrik-SQLUnMountLog-" + $Now.ToString("yyyy-MM-dd") + "@" + $Now.ToString("HH-mm-ss") + ".log"
Start-Transcript -Path $Log -NoClobber 
$SQLiveMounts = import-csv $SQLLiveMountCSV
################################################
# Building Rubrik API string & invoking REST API
################################################
$baseURL = "https://" + $RubrikCluster + "/api/v1/"
$xRubrikSessionURL = $baseURL + "session"
$authInfo = ("{0}:{1}" -f $RubrikUser,$RubrikPassword)
$authInfo = [System.Text.Encoding]::UTF8.GetBytes($authInfo)
$authInfo = [System.Convert]::ToBase64String($authInfo)
$headers = @{Authorization=("Basic {0}" -f $authInfo)}
$TypeJSON = "application/json"
# Authentication with API
Try 
{
$xRubrikSessionResponse = Invoke-WebRequest -Uri $xRubrikSessionURL -Headers $headers -Method POST -Body $sessionBody -ContentType $TypeJSON
}
Catch 
{
Write-Host $_.Exception.ToString()
$error[0] | Format-List -Force
}
# Extracting the token from the JSON response
$xRubrikSession = (ConvertFrom-Json -InputObject $xRubrikSessionResponse.Content)
$RubrikSessionHeader = @{'Authorization' = "Bearer $($xRubrikSession.token)"}
###############################################
# Getting list of SQL Databases
###############################################
$SQLDBListURL = $baseURL+"mssql/db?limit=5000"
Try 
{
$SQLDBListJSON = Invoke-RestMethod -Uri $SQLDBListURL -TimeoutSec 100 -Headers $RubrikSessionHeader -ContentType $TypeJSON
$SQLDBList = $SQLDBListJSON.data
}
Catch 
{
Write-Host $_.Exception.ToString()
$error[0] | Format-List -Force
}
###############################################
# Getting list of SQL Instances
###############################################
$SQLInstanceListURL = $baseURL+"mssql/instance?limit=5000"
Try 
{
$SQLInstanceJSON = Invoke-RestMethod -Uri $SQLInstanceListURL -TimeoutSec 100 -Headers $RubrikSessionHeader -ContentType $TypeJSON
$SQLInstanceList = $SQLInstanceJSON.data
}
Catch 
{
Write-Host $_.Exception.ToString()
$error[0] | Format-List -Force
}
###############################################
# Building a list of SQL instances by hostname, needed to enable selection of the correct instance
###############################################
$SQLInstanceArray = @()
ForEach ($SQLInstance in $SQLInstanceList)
{
$SQLInstanceName = $SQLInstance.name
$SQLInstanceID = $SQLInstance.id
$SQLInstanceHostName = $SQLInstance.rootProperties.rootName
$SQLInstanceHostID = $SQLInstance.rootProperties.rootId
# Adding to array
$SQLInstanceArrayLine = new-object PSObject
$SQLInstanceArrayLine | Add-Member -MemberType NoteProperty -Name "InstanceName" -Value "$SQLInstanceName"
$SQLInstanceArrayLine | Add-Member -MemberType NoteProperty -Name "InstanceID" -Value "$SQLInstanceID"
$SQLInstanceArrayLine | Add-Member -MemberType NoteProperty -Name "HostName" -Value "$SQLInstanceHostName"
$SQLInstanceArrayLine | Add-Member -MemberType NoteProperty -Name "HostNameID" -Value "$SQLInstanceHostID"
$SQLInstanceArray += $SQLInstanceArrayLine
}
###############################################
# Getting list of Hosts - Needed to ensure host is registered
###############################################
$WindowsHostsURL = $baseURL+"host?limit=5000"
Try 
{
$WindowsHostsJSON = Invoke-RestMethod -Uri $WindowsHostsURL -TimeoutSec 100 -Headers $RubrikSessionHeader -ContentType $TypeJSON
$WindowsHosts = $WindowsHostsJSON.data
}
Catch 
{
Write-Host $_.Exception.ToString()
$error[0] | Format-List -Force
}
###############################################
# Getting list of SQL Live Mounts - For unmounting
###############################################
$SQLActiveLiveMountsURL = $baseURL+"mssql/db/mount"
Try 
{
$SQLActiveLiveMountsJSON = Invoke-RestMethod -Uri $SQLActiveLiveMountsURL -TimeoutSec 100 -Headers $RubrikSessionHeader -ContentType $TypeJSON
$SQLActiveLiveMounts = $SQLActiveLiveMountsJSON.data
}
Catch 
{
Write-Host $_.Exception.ToString()
$error[0] | Format-List -Force
}
$SQLActiveLiveMounts
###############################################
# Start For Each SQL DB below
###############################################
ForEach ($SQLiveMount in $SQLiveMounts)
{
# Setting variables
$SourceSQLHostName = $SQLiveMount.SourceSQLHostName
$SourceInstanceName = $SQLiveMount.SourceInstanceName
$SourceDatabaseName = $SQLiveMount.SourceDatabaseName
$TargetSQLHostName = $SQLiveMount.TargetSQLHostName
$TargetInstanceName = $SQLiveMount.TargetInstanceName
$TargetDatabaseName = $SQLiveMount.TargetDatabaseName
# Inserting space in log for readability
"--------------------------------------------"
"Performing UnMount For:
DB:$TargetDatabaseName Instance:$TargetInstanceName Host:$TargetSQLHostName"
################################################
# Getting IDs needed
################################################
# Getting target instance ID
$TargetInstanceID = $SQLInstanceArray | Where-Object {(($_.HostName -eq $TargetSQLHostName) -AND ($_.InstanceName -eq $TargetInstanceName))} | Select -ExpandProperty InstanceID -First 1
"TargetInstanceID:$TargetInstanceID"
# Selecting active Live mount ID
$SQLLiveMountID = $SQLActiveLiveMounts | Where-Object {(($_.targetRootName -eq $TargetSQLHostName) -AND ($_.sourceDatabaseName -eq $SourceDatabaseName) -AND ($_.targetInstanceID -eq $TargetInstanceID) -AND ($_.mountedDatabaseName -like $TargetDatabaseName))} | select -ExpandProperty id
################################################
# Performing IF statement to only try to UnMount databases if a valid ID is found
################################################
# IF ID is not null, this means the live mount in the CSV was found in $SQLActiveLiveMounts
IF ($SQLLiveMountID)
{
"Active Live Mount Found"
# Creating DELETE URL
$SQLDBLiveMountDeleteURL = $baseURL+"mssql/db/mount/"+$SQLLiveMountID
# DELETE API Call
Try 
{
$SQLDBLiveMountDelete = Invoke-RestMethod -Method Delete -Uri $SQLDBLiveMountDeleteURL -Body $SQLDBLiveMountJSON -TimeoutSec 100 -Headers $RubrikSessionHeader -ContentType $TypeJSON
$SQLDBLiveMountDeleteSuccess = $TRUE
}
Catch 
{
$SQLDBLiveMountDeleteSuccess = $FALSE
Write-Host $_.Exception.ToString()
$error[0] | Format-List -Force
}
"SQLDBLiveMountDeleteSuccess:$SQLDBLiveMountDeleteSuccess"
# End of IF statement to delete live mounts below
}
# End of IF statement to delete live mounts above
ELSE
{
"Active Live Mount Not Found"
}
# End of for each SQL DB below
}
# End of for each SQL DB above
# Inserting space in log for readability
"--------------------------------------------"
"End of LiveMount Script"
################################################
# Stopping logging
################################################
Stop-Transcript
###############################################
# End of script
###############################################

A quick trip to the Rubrik GUI and my SQL server confirms the live mounts have gone:

Perfect for stopping the live mounts before your backup window starts or before your next run of the mount script. And that’s it. You have now delivered what is probably the single biggest value add any backup solution has ever had in your environment. One to put on your selection criteria for your next backup platform. 😊 Happy scripting,

Joshua

  1. Manu MS Manu MS

    Cool job!! Good presentation. Like to know the Rubrik Live mount feature can be used for all SQL version or there any limitation. Isn’t live mount job is only for testing the DBs is good for a restore? If the original production DB is corrupted can the same DB can brought up without restoring the data to SQL host?

    • Joshua Stenhouse Joshua Stenhouse

      Hey! The Rubrik SQL live mount feature supports any version of SQL, supported by Microsoft, so that is SQL 2008 onwards. The live mount of a SQL DB definitely isn’t just for testing the DB is good for a restore. While this is a good use case, it’s missing the huge value of dev/test and reporting using secondary instances and the last backup of the DB. Also, for table level restores the DBA can perform a live mount to pull the 1 table needed and not have to wait for a 2TB SQL database to restore first (never mind the time, think of the temporary disk space needed etc). If the original DB is corrupted then the same DB can be live mounted, but you either need to take the existing DB offline or rename one of them.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: