Blog Post

Azure SQL Blog
6 MIN READ

Automate migration to SQL Managed Instance using Azure PowerShell and DbaTools

JovanPop's avatar
JovanPop
Icon for Microsoft rankMicrosoft
Aug 30, 2019

In Microsoft Azure, you can easily migrate your databases from SQL Server on-premises or Azure VMs to the fully-managed PaaS database service Azure SQL Database Managed Instance. In this post you will see how to create PowerShell scripts that automate migration to Managed Instance using Azure PowerShell and DbaTools.

The approach used in this article is OFFLINE migration. You should stop the activities on your source SQL Server instance while the databases and server-level objects are copied to the target Managed Instance. If you need ONLINE migration that will enable you to use your source databases while they are moving to Managed Instance, take a look at the Database Migration Service.

Typically, the steps involved in an offline migration process are:

  • Create an Azure Blob Storage account that will be used to temporary hold the database backups that will be moved from SQL Server to Managed Instance.
  • Back up the databases to Azure Blob Storage and restore them from Azure Blob Storage to Managed Instance.
  • Migrate server-level objects such as logins, agent jobs from the source to destination instance.

In this article, I will use Azure PowerShell to create and manage necessary Azure resources, and DBATools PowerShell library to initiate migration.

 

NOTE: This procedure is based on the assumption that the machine where you are running this script on has access both to the source SQL Server and the target Managed Instance.

Prerequisites

Before you begin, you should make sure that you have installed all necessary PowerShell libraries. The following PowerShell modules are used:

 

Install-Module Az.Resources
Install-Module Az.Storage
Install-Module dbatools

 

 

NOTE: Make sure that you have the latest 150.18147.0 or higher version of Microsoft.SqlServer.SqlManagementObjects installed or these commands will fail. If you don't install anything, DbaTools will include the latest version of SMO. However, if you have the older version and include it in the PowerShell session, the script will fail.

Parameter definition

As a first step, populate the parameters that define the names of source/target instances and temporary Azure Blob Storage account used in this sample:

 

# temporary resources needed for backups
$location = "westus"
$resourceGroup = "temp-migration-demo-rg"
$blobStorageAccount = "temp-migrationdemostorage"
$containerName = "backups"
 
# source and target instances
$sourceInstance = "SOURCESQLSERVER"
$sourceDatabase = "WideWorldImporters"
 
$targetInstance = "targetmi.public.920d05d7463d.database.windows.net,3342"
$targetDatabase = "WideWorldImporters"

 

Change these parameters depending on your needs. In this sample, I am using a public endpoint to connect to Managed Instance. If you don’t have a public endpoint, you can set up a Point-to-site connection or run the script from the virtual machine that is placed in the same subnet as your Managed Instance.

NOTE: Make sure that you use the same region where your Managed Instance is placed because this will speed-up the database restore process.

Storage setup

In order to move your databases, you need to create a temporary Azure Blob Storage account. If you already have one, you can skip this step.

The following PowerShell script creates an Azure Blob Storage account that will be used in this sample:

 

New-AzResourceGroup -Name $resourceGroup -Location $location
 
$storageAccount = New-AzStorageAccount -ResourceGroupName $resourceGroup `
-Name $blobStorageAccount `
-Location $location `
-SkuName Standard_LRS `
-Kind StorageV2
 
$ctx = $storageAccount.Context
New-AzStorageContainer -Name $containerName -Context $ctx -Permission Container

 

Once you execute this script, you will have Azure Blob Storage account ready to be used in the migration.

Source instance setup

Once you create an Azure Blob Storage account, you need to generate a SAS key that will enable your SQL Server instance to access the Azure Blob Storage account and put the database backups there. This SAS key will be represented as a Credential object in SQL Server instance:

 

$sas = (New-AzStorageAccountSASToken -Service Blob -ResourceType Object -Permission "rw" -Context $ctx).TrimStart('?')
# Note: it must have r permission!
 
$sourceCred = New-DbaCredential -SqlInstance $sourceInstance `
                           -Name "https://$blobStorageAccount.blob.core.windows.net/$containerName" `
                           -Identity "SHARED ACCESS SIGNATURE" `
                           -SecurePassword (ConvertTo-SecureString $sas -AsPlainText -Force)

 

Now you are ready to back up your SQL Server databases to Azure Blob Storage.

Database migration

With the prepared Azure Blob Storage account and credentials, you can take the backups of you SQL Server databases and put them to Azure Blob Storage. I will assume that you have SQL Server 2012 (11.x) SP1 CU2 or higher version that supports BACKUP TO URL. If not, you would need to modify the script slightly, by taking a backup of the database to a local folder and then uploading the .bak file from the local folder to Azure Blob Storage container.

The DbaTools command that backup your database to the temporary Azure Blob Storage account is shown below:

 

Backup-DbaDatabase -SqlInstance $sourceInstance -Database $sourceDatabase `
                   -AzureBaseUrl "https://$blobStorageAccount.blob.core.windows.net/$containerName" `
                   -BackupFileName "WideWorldImporters.bak" `
               `   -Type Full -Checksum -CopyOnly

 

You can put a comma-separated list of databases that you want to migrate in the parameter -Database. Once you complete this step, you will have the backups of all databases that are ready to be restored on Managed Instance.

If you are taking a backup of a large database you might want to create a striped backup by using multiple URLs as target, and set of the following options: COMPRESSION, MAXTRANSFERSIZE = 4194304, and BLOCKSIZE = 65536. Please refer to Backing up a VLDB to Azure Blob Storage for more information on how to use these options.

Migrating the databases to the target instance

Now you need to setup the target Managed Instance where you need to create SAS token that will enable the Managed Instance to read .bak file from Azure Blob Storage, create a credential with this SAS token, and restore the database:

 

## Generate new SAS token that will read .bak file
$sas = (New-AzStorageAccountSASToken -Service Blob -ResourceType Object -Permission "r" -Context $ctx).TrimStart('?') # -ResourceType Container,Object
 
$targetLogin = Get-Credential -Message "Login to target Managed Instance as:"
$target = Connect-DbaInstance -SqlInstance $targetInstance -SqlCredential $targetLogin

$targetCred = New-DbaCredential -SqlInstance $target `
                           -Name "https://$blobStorageAccount.blob.core.windows.net/$containerName" `
                           -Identity "SHARED ACCESS SIGNATURE" `
                           -SecurePassword (ConvertTo-SecureString $sas -AsPlainText -Force) `
                           -Force
Restore-DbaDatabase -SqlInstance $target -Database $targetDatabase `
                   -Path "https://$blobStorageAccount.blob.core.windows.net/$containerName/WideWorldImporters.bak"

 

This script will prompt for the SQL login details that should be used to access Managed Instance.

As a result, you will get your database restored on the target Managed Instance and your database migration will be completed.

Server-level objects migration

Once you migrate your database objects, you might also need to migrate server-level objects such as Agent jobs/operators, Database Mail configurations, server-level logins, etc.

DbaTools provides a set of useful scripts that you can apply to migrate these objects using Copy-Dba commands:

 

Copy-DbaSysDbUserObject -Source $sourceInstance -Destination $targetInstance -DestinationSqlCredential $targetLogin
Copy-DbaDbMail -Source $sourceInstance -Destination $targetInstance -DestinationSqlCredential $targetLogin
Copy-DbaAgentOperator -Source $sourceInstance -Destination $targetInstance -DestinationSqlCredential $targetLogin
Copy-DbaAgentJobCategory -Source $sourceInstance -Destination $targetInstance -DestinationSqlCredential $targetLogin
Copy-DbaAgentJob -Source $sourceInstance -Destination $targetInstance -DestinationSqlCredential $targetLogin
Copy-DbaAgentSchedule -Source $sourceInstance -Destination $targetInstance -DestinationSqlCredential $targetLogin
Copy-DbaLogin -Source $sourceInstance -Destination $targetInstance -DestinationSqlCredential $targetLogin -ExcludeSystemLogins

 

In this sample selected object types from the source SQL Server are copied to target Managed Instance. You can change this part and select the objects that should be migrated.

Cleanup

If your Azure Blob Storage account is temporary storage that you need to use only while you are moving databases, you can remove these resources using the following PowerShell command:

 

Remove-AzResourceGroup -Name $resourceGroup -Force

 

Conclusion

Azure PowerShell and DBATools PowerShell libraries enable you to easily script and automate and customize all parts of the migration process.

This type of migration is an offline migration where you probably need to stop any changes that might happen on the source instance until you finish the migration. As an alternative, you can use Database Migration Service and perform an online migration.

Updated Dec 04, 2020
Version 11.0
  • KFeit's avatar
    KFeit
    Copper Contributor

    This is a great post to provide a simple and efficient method for migrating to Managed Instance.  However, it is using SAS tokens on the source backup, which are only supported for SQL 2016 and later.  Can you please provide an example for performing a backup to a page blob with the credential specified on the Backup-DbaDatabase command?  Many organizations are on 2012 or 2014 and may be interested in moving to Managed Instance instead of upgrading on premise.