Skip to content

Commit 5382e8e

Browse files
Merge pull request #191779 from sasapopo/main
Article on SQL Managed Instance link script based database failover to Azure
2 parents f88d4a4 + bb10b41 commit 5382e8e

File tree

3 files changed

+284
-12
lines changed

3 files changed

+284
-12
lines changed
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
---
2+
title: Fail over database with link feature with T-SQL and PowerShell scripts
3+
titleSuffix: Azure SQL Managed Instance
4+
description: This guide teaches you how to use the SQL Managed Instance link with scripts to fail over database from SQL Server to Azure SQL Managed Instance.
5+
services: sql-database
6+
ms.service: sql-managed-instance
7+
ms.subservice: data-movement
8+
ms.custom:
9+
ms.devlang:
10+
ms.topic: guide
11+
author: sasapopo
12+
ms.author: sasapopo
13+
ms.reviewer: mathoma
14+
ms.date: 03/15/2022
15+
---
16+
17+
# Failover (migrate) database with Azure SQL Managed Instance link feature with T-SQL and PowerShell scripts
18+
19+
[!INCLUDE[appliesto-sqlmi](../includes/appliesto-sqlmi.md)]
20+
21+
This article teaches you to use T-SQL and PowerShell scripts for [Managed Instance link feature](link-feature.md) to fail over (migrate) your database from SQL Server to Azure SQL Managed Instance.
22+
23+
> [!NOTE]
24+
> The link feature for Azure SQL Managed Instance is currently in preview.
25+
26+
> [!NOTE]
27+
> Configuration on Azure side is done with PowerShell that calls SQL Managed Instance REST API. Support for Azure PowerShell and CLI will be released in the upcomming weeks. At that point this article will be updated with the simplified PowerShell scripts.
28+
29+
> [!TIP]
30+
> SQL Managed Instance link database failover can be set up with [SSMS wizard](managed-instance-link-use-ssms-to-failover-database.md).
31+
32+
Database failover from SQL Server instance to SQL Managed Instance breaks the link between the two databases. Failover stops replication and leaves both databases in an independent state, ready for individual read-write workloads.
33+
34+
To start migrating database to the SQL Managed Instance, first stop the application workload to the SQL Server during your maintenance hours. This is required to enable SQL Managed Instance to catchup with the database replication and make migration to Azure without any data loss.
35+
36+
While database is a part of Always On Availability Group, it isn't possible to set it to read-only mode. You'll need to ensure that your application(s) aren't committing transactions to SQL Server.
37+
38+
## Switch the replication mode from asynchronous to synchronous
39+
40+
The replication between SQL Server and SQL Managed Instance is asynchronous by default. Before you perform database migration to Azure, the link needs to be switched to synchronous mode. Synchronous replication across distances might slow down transactions on the primary SQL Server.
41+
Switching from async to sync mode requires replication mode change on SQL Managed Instance and SQL Server.
42+
43+
## Switch replication mode on Managed Instance
44+
45+
Use the following PowerShell script to call REST API that changes the replication mode from asynchronous to synchronous on SQL Managed Instance. We suggest you execute the REST API call using Azure Cloud Shell in Azure portal.
46+
47+
Replace `<YourSubscriptionID>` with your subscription ID and replace `<ManagedInstanceName>` with the name of your managed instance. Replace `<DAGName>` with the name of Distributed Availability Group link for which you’d like to get the status.
48+
49+
```powershell
50+
# ====================================================================================
51+
# POWERSHELL SCRIPT TO SWITCH REPLICATION MODE SYNC-ASYNC ON MANAGED INSTANCE
52+
# USER CONFIGURABLE VALUES
53+
# (C) 2021-2022 SQL Managed Instance product group
54+
# ====================================================================================
55+
# Enter your Azure Subscription ID
56+
$SubscriptionID = "<SubscriptionID>"
57+
# Enter your Managed Instance name – example "sqlmi1"
58+
$ManagedInstanceName = "<ManagedInstanceName>"
59+
# Enter the Distributed Availability Group name
60+
$DAGName = "<DAGName>"
61+
62+
# ====================================================================================
63+
# INVOKING THE API CALL -- THIS PART IS NOT USER CONFIGURABLE
64+
# ====================================================================================
65+
# Log in and select subscription if needed
66+
if ((Get-AzContext ) -eq $null)
67+
{
68+
echo "Logging to Azure subscription"
69+
Login-AzAccount
70+
}
71+
Select-AzSubscription -SubscriptionName $SubscriptionID
72+
73+
# Build URI for the API call
74+
#
75+
$miRG = (Get-AzSqlInstance -InstanceName $ManagedInstanceName).ResourceGroupName
76+
$uriFull = "https://management.azure.com/subscriptions/" + $SubscriptionID + "/resourceGroups/" + $miRG+ "/providers/Microsoft.Sql/managedInstances/" + $ManagedInstanceName + "/distributedAvailabilityGroups/" + $DAGName + "?api-version=2021-05-01-preview"
77+
echo $uriFull
78+
79+
# Build API request body
80+
#
81+
82+
$bodyFull = @"
83+
{
84+
"properties":{
85+
"ReplicationMode":"sync"
86+
}
87+
}"@
88+
89+
echo $bodyFull
90+
91+
# Get auth token and build the header
92+
#
93+
$azProfile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile
94+
$currentAzureContext = Get-AzContext
95+
$profileClient = New-Object Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient($azProfile)
96+
$token = $profileClient.AcquireAccessToken($currentAzureContext.Tenant.TenantId)
97+
$authToken = $token.AccessToken
98+
$headers = @{}
99+
$headers.Add("Authorization", "Bearer "+"$authToken")
100+
101+
# Invoke API call
102+
#
103+
echo "Invoking API call switch Async-Sync replication mode on Managed Instance"
104+
Invoke-WebRequest -Method PATCH -Headers $headers -Uri $uriFull -ContentType "application/json" -Body $bodyFull
105+
```
106+
107+
## Switch replication mode on SQL Server
108+
109+
Use the following T-SQL script to change the replication mode of Distributed Availability Group on SQL Server from async to sync. Replace `<DAGName>` with the name of Distributed Availability Group, and replace `<AGName>` with the name of Availability Group created on SQL Server. In addition, replace `<ManagedInstanceName>` with the name of your SQL Managed Instance.
110+
With this step, the migration of the database from SQL Server to SQL Managed Instance is completed.
111+
112+
```sql
113+
-- Sets the Distributed Availability Group to synchronous commit.
114+
-- ManagedInstanceName example 'sqlmi1'
115+
USE master
116+
GO
117+
ALTER AVAILABILITY GROUP [<DAGName>]
118+
MODIFY
119+
AVAILABILITY GROUP ON
120+
'<AGName>' WITH
121+
(AVAILABILITY_MODE = SYNCHRONOUS_COMMIT),
122+
'<ManagedInstanceName>' WITH
123+
(AVAILABILITY_MODE = SYNCHRONOUS_COMMIT);
124+
```
125+
126+
To validate change of the link replication, execute the following DMV, and expected results are shown below. They're indicating SYNCHRONOUS_COMIT state.
127+
128+
```sql
129+
-- Verifies the state of the distributed availability group
130+
SELECT
131+
ag.name, ag.is_distributed, ar.replica_server_name,
132+
ar.availability_mode_desc, ars.connected_state_desc, ars.role_desc,
133+
ars.operational_state_desc, ars.synchronization_health_desc
134+
FROM
135+
sys.availability_groups ag
136+
join sys.availability_replicas ar
137+
on ag.group_id=ar.group_id
138+
left join sys.dm_hadr_availability_replica_states ars
139+
on ars.replica_id=ar.replica_id
140+
WHERE
141+
ag.is_distributed=1
142+
```
143+
144+
With both SQL Managed Instance, and SQL Server being switched to Sync mode, the replication between the two entities is now synchronous. If you require to reverse this state, follow the same steps and set async state for both SQL Server and SQL Managed Instance.
145+
146+
## Check LSN values on both SQL Server and Managed Instance
147+
148+
To complete the migration, we need to ensure that the replication has completed. For this, you need to ensure that LSNs (Log Sequence Numbers) indicating the log records written for both SQL Server and SQL Managed Instance are the same. Initially, it's expected that SQL Server LSN will be higher than LSN number on SQL Managed Instance. The difference is caused by the fact that SQL Managed Instance might be lagging somewhat behind the primary SQL Server due to network latency. After some time, LSNs on SQL Managed Instance and SQL Server should match and stop changing, as the workload on SQL Server should be stopped.
149+
150+
Use the following T-SQL query on SQL Server to read the LSN number of the last recorded transaction log. Replace `<DatabaseName>` with your database name and look for the last hardened LSN number, as shown below.
151+
152+
```sql
153+
-- Obtain last hardened LSN for a database on SQL Server.
154+
SELECT
155+
ag.name AS [Replication group],
156+
db.name AS [Database name],
157+
drs.database_id AS [Database ID],
158+
drs.group_id,
159+
drs.replica_id,
160+
drs.synchronization_state_desc AS [Sync state],
161+
drs.end_of_log_lsn AS [End of log LSN],
162+
drs.last_hardened_lsn AS [Last hardened LSN]
163+
FROM
164+
sys.dm_hadr_database_replica_states drs
165+
inner join sys.databases db on db.database_id = drs.database_id
166+
inner join sys.availability_groups ag on drs.group_id = ag.group_id
167+
WHERE
168+
ag.is_distributed = 1 and db.name = '<DatabaseName>'
169+
```
170+
171+
Use the following T-SQL query on SQL Managed Instance to read the LSN number of the last hardened LSN number for your database. Replace `<DatabaseName>` with your database name.
172+
173+
Query shown below will work on General Purpose SQL Managed Instance. For Business Critical Managed Instance, you will need to uncomment `and drs.is_primary_replica = 1` at the end of the script. On Business Critical, this filter will make sure that only primary replica details are read.
174+
175+
```sql
176+
-- Obtain LSN for a database on SQL Managed Instance.
177+
SELECT
178+
db.name AS [Database name],
179+
drs.database_id AS [Database ID],
180+
drs.group_id,
181+
drs.replica_id,
182+
drs.synchronization_state_desc AS [Sync state],
183+
drs.end_of_log_lsn AS [End of log LSN],
184+
drs.last_hardened_lsn AS [Last hardened LSN]
185+
FROM
186+
sys.dm_hadr_database_replica_states drs
187+
inner join sys.databases db on db.database_id = drs.database_id
188+
WHERE
189+
db.name = '<DatabaseName>'
190+
-- for BC add the following as well
191+
-- AND drs.is_primary_replica = 1
192+
```
193+
194+
Verify once again that your workload is stopped on SQL Server. Check that LSNs on both SQL Server and SQL Managed Instance match, and that they remain matched and unchanged for some time. Stable LSN numbers on both ends indicate that tail log has been replicated to SQL Managed Instance and workload is effectively stopped. Proceed to the next step to initiate database failover and migration to Azure.
195+
196+
## Initiate database failover and migration to Azure
197+
198+
SQL Managed Instance link database failover and migration to Azure is accomplished by invoking REST API call. This will close the link and complete the replication on SQL Managed Instance. Replicated database will become read-write on SQL Managed Instance.
199+
200+
Use the following API to initiate database failover to Azure. Replace `<YourSubscriptionID>` with your actual Azure subscription ID. Replace `<RG>` with the resource group where your SQL Managed Instance is deployed and replace `<ManagedInstanceName>` with the name of our SQL Managed Instance. In addition, replace `<DAGName>` with the name of Distributed Availability Group made on SQL Server.
201+
202+
```PowerShell
203+
# ====================================================================================
204+
# POWERSHELL SCRIPT TO FAILOVER AND MIGRATE DATABASE WITH SQL MANAGED INSTANCE LINK
205+
# USER CONFIGURABLE VALUES
206+
# (C) 2021-2022 SQL Managed Instance product group
207+
# ====================================================================================
208+
# Enter your Azure Subscription ID
209+
$SubscriptionID = "<SubscriptionID>"
210+
# Enter your Managed Instance name – example "sqlmi1"
211+
$ManagedInstanceName = "<ManagedInstanceName>"
212+
# Enter the Distributed Availability Group link name
213+
$DAGName = "<DAGName>"
214+
215+
# ====================================================================================
216+
# INVOKING THE API CALL -- THIS PART IS NOT USER CONFIGURABLE.
217+
# ====================================================================================
218+
# Log in and select subscription if needed
219+
if ((Get-AzContext ) -eq $null)
220+
{
221+
echo "Logging to Azure subscription"
222+
Login-AzAccount
223+
}
224+
Select-AzSubscription -SubscriptionName $SubscriptionID
225+
226+
# Build URI for the API call
227+
#
228+
$miRG = (Get-AzSqlInstance -InstanceName $ManagedInstanceName).ResourceGroupName
229+
$uriFull = "https://management.azure.com/subscriptions/" + $SubscriptionID + "/resourceGroups/" + $miRG+ "/providers/Microsoft.Sql/managedInstances/" + $ManagedInstanceName + "/distributedAvailabilityGroups/" + $DAGName + "?api-version=2021-05-01-preview"
230+
echo $uriFull
231+
232+
# Get auth token and build the header
233+
#
234+
$azProfile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile
235+
$currentAzureContext = Get-AzContext
236+
$profileClient = New-Object Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient($azProfile)
237+
$token = $profileClient.AcquireAccessToken($currentAzureContext.Tenant.TenantId)
238+
$authToken = $token.AccessToken
239+
$headers = @{}
240+
$headers.Add("Authorization", "Bearer "+"$authToken")
241+
242+
# Invoke API call
243+
#
244+
Invoke-WebRequest -Method DELETE -Headers $headers -Uri $uriFull -ContentType "application/json"
245+
```
246+
247+
## Cleanup Availability Group and Distributed Availability Group on SQL Server
248+
249+
After breaking the link and migrating database to Azure SQL Managed Instance, consider cleaning up Availability Group and Distributed Availability Group on SQL Server if they aren't used otherwise.
250+
Replace `<DAGName>` with the name of the Distributed Availability Group on SQL Server and replace `<AGName>` with Availability Group name on the SQL Server.
251+
252+
``` sql
253+
DROP AVAILABILITY GROUP <DAGName>
254+
GO
255+
DROP AVAILABILITY GROUP <AGName>
256+
GO
257+
```
258+
259+
With this step, the migration of the database from SQL Server to Managed Instance has been completed.
260+
261+
## Next steps
262+
263+
For more information on the link feature, see the following resources:
264+
265+
- [Managed Instance link – connecting SQL Server to Azure reimagined](https://aka.ms/mi-link-techblog).
266+
- [Prepare for SQL Managed Instance link](./managed-instance-link-preparation.md).
267+
- [Use SQL Managed Instance link with scripts to replicate database](./managed-instance-link-use-scripts-to-replicate-database.md).
268+
- [Use SQL Managed Instance link via SSMS to replicate database](./managed-instance-link-use-ssms-to-replicate-database.md).
269+
- [Use SQL Managed Instance link via SSMS to migrate database](./managed-instance-link-use-ssms-to-failover-database.md).

0 commit comments

Comments
 (0)