This guide shows you how to migrate databases from a self-managed SQL Server Enterprise Edition instance to Cloud SQL for SQL Server Enterprise Edition over a private network connection by using a Distributed Availability Group (DAG) in Database Migration Service.
With a DAG migration, Database Migration Service streams both the initial full load
(known as the FULL_DUMP phase) and continuous transaction log replication
(known as the Change Data Capture - CDC - phase) directly over
the network between your source Availability Group and your destination
Cloud SQL for SQL Server Availability Group. For more information about the
architecture, prerequisites, and limitations of DAG migrations, see
About Distributed Availability Group (DAG) migrations.
To migrate by using backup files stored in Cloud Storage, see
Migrate your SQL Server databases to Cloud SQL for SQL Server.
To perform a Distributed Availability Group migration, you complete the following high-level tasks:
- Create and prepare your destination Cloud SQL for SQL Server instance.
- Prepare your source SQL Server instance and Availability Group.
- Establish bidirectional private network connectivity and configure a Linked Server.
- Create connection profiles and run the migration job.
- Monitor and verify your migration.
- Promote, fail back, or complete the migration.
Costs
For homogeneous migrations to Cloud SQL, Database Migration Service is offered at no additional charge. However, standard Cloud SQL and network pricing applies. To estimate your usage costs, use the pricing calculator.
Before you begin
- Verify that your source and destination databases meet all prerequisites
and limitations for Distributed Availability Group migrations (including
running Enterprise Edition, storing data files in the default data directory,
and not using
saas the database owner). See About Distributed Availability Group (DAG) migrations. - Choose the Google Cloud region for your migration. Database Migration Service is a fully regional product; all entities related to your migration (source and destination connection profiles, migration job, and destination Cloud SQL for SQL Server instance) must reside in the same region.
- In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
- Enable the Database Migration Service, Compute Engine, and Cloud SQL Admin APIs.
Required roles
Make sure that the following IAM roles are granted in your Google Cloud project:
- User account that performs the migration:
- Database Migration Admin (
roles/datamigration.admin) - Cloud SQL Editor (
roles/cloudsql.editor)
- Database Migration Admin (
- Database Migration Service service account (
service-<var>PROJECT_NUMBER</var>@gcp-sa-datamigration.iam.gserviceaccount.com):- Database Migration Service Agent (
roles/datamigration.serviceAgent) - Cloud SQL Editor (
roles/cloudsql.editor) - Cloud SQL Studio User (
roles/cloudsql.studioUser)
- Database Migration Service Agent (
For more information about granting roles, see Manage access.
Create and prepare your destination Cloud SQL for SQL Server instance
In this step, you create your destination Cloud SQL for SQL Server Enterprise Edition instance and enable the database flag required for Linked Servers.
- Create your destination Cloud SQL for SQL Server instance. For detailed
creation instructions, see
Create a Cloud SQL for SQL Server instance.
Ensure that your instance meets the following requirements for Distributed
Availability Group migrations:
- Select Enterprise Edition (version 2017, 2019, 2022, or 2025).
- Configure private networking to align with how you plan to connect your
source SQL Server instance and destination Cloud SQL for SQL Server
instance. Enable
Private Services Access
if you plan to connect your instances over Virtual Private Cloud peering,
or use
Private Service Connect if you plan to connect your
instances by using an inbound Private Service Connect endpoint and an outbound
Private Service Connect network attachment.
Don't enable both Private Services Access and Private Service Connect on the same destination Cloud SQL for SQL Server instance. Cloud SQL for SQL Server doesn't support Linked Servers when both are enabled. For full networking setup details, see Establish bidirectional private network connectivity.
- Keep Point-in-time recovery (PITR) disabled and don't add read replicas until after you complete and delete the DAG migration job.
- If any source database is owned by a Windows Active Directory login, either change the source database owner to a SQL login before migrating, or join the destination Cloud SQL for SQL Server instance to Active Directory so that Database Migration Service can automatically create the corresponding Windows login on the destination instance when the migration job starts. For instructions, see Configure Managed Microsoft AD for Cloud SQL for SQL Server.
- Enable the
cloudsql enable linked serversdatabase flag (set toon) on your destination Cloud SQL for SQL Server instance. For instructions on setting flags, see Manage linked servers and Configure database flags.This flag is needed at a later point in this guide when you create and verify the Linked Server on your destination Cloud SQL for SQL Server instance.
Prepare your source SQL Server instance
In this step, you enable Always On Availability Groups on your source SQL Server instance, create a Database Mirroring endpoint and certificate, create a dedicated SQL login for Database Migration Service, and prepare your source Availability Group.
Enable Always On Availability Groups
Ensure that the Always On Availability Groups feature is enabled on your source SQL Server instance:
- For Windows, see Enable and disable Always On availability groups in the Microsoft documentation.
- For Linux, see Configure SQL Server Always On availability group for high availability on Linux in the Microsoft documentation.
Create the Database Mirroring endpoint and certificate
In SQL Server, Distributed Availability Groups stream data and
transaction logs between instances over TCP DATABASE_MIRRORING (DBM)
endpoints (default port 5022). Because your self-managed SQL Server
instance and your destination Cloud SQL for SQL Server instance are standalone
instances, they require certificate-based mutual authentication and AES
encryption to establish trust over the DBM endpoint.
You only need to create a certificate and bind it to the DATABASE_MIRRORING
endpoint on your source SQL Server instance. You don't need to
manually export certificate files or create certificates on your destination
Cloud SQL for SQL Server instance:
- When you start the migration job, Database Migration Service automatically configures
the
DATABASE_MIRRORINGendpoint and certificate on your destination Cloud SQL for SQL Server instance and uses your Linked Server to exchange the public keys between both instances. - When you delete the migration job after completing your cutover, Database Migration Service automatically removes the imported certificates from both instances.
If your source SQL Server instance doesn't already have a
DATABASE_MIRRORING endpoint authenticated with a certificate, create one:
- Connect to your source instance with a SQL client, for example the
sqlcmdutility. - Run the following T-SQL commands to create a database master key, a
certificate, and a
DATABASE_MIRRORINGendpoint listening on your chosenDBMport (default5022):USE [master]; GO IF NOT EXISTS (SELECT * FROM sys.symmetric_keys WHERE symmetric_key_id = 101) BEGIN CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'MASTER_KEY_PASSWORD'; END GO CREATE CERTIFICATE [SOURCE_CERT_NAME] WITH SUBJECT = 'AlwaysOn AG Certificate', EXPIRY_DATE = 'CERT_EXPIRY_DATE'; GO CREATE ENDPOINT [HADR_ENDPOINT_NAME] STATE = STARTED AS TCP (LISTENER_PORT = SOURCE_DBM_PORT_NUMBER) FOR DATABASE_MIRRORING ( ROLE = ALL, AUTHENTICATION = CERTIFICATE [SOURCE_CERT_NAME], ENCRYPTION = REQUIRED ALGORITHM AES ); GO
Replace the following:
MASTER_KEY_PASSWORDwith a password to encrypt the database master key.SOURCE_CERT_NAMEwith a name for your source Database Mirroring certificate (for example,dbmCertificate).CERT_EXPIRY_DATEwith the expiration date for the certificate inYYYYMMDDformat.HADR_ENDPOINT_NAMEwith the name of your Database Mirroring endpoint.SOURCE_DBM_PORT_NUMBERwith the TCP port number for Database Mirroring traffic (default5022).
Create the dedicated Database Migration Service login and permissions
Database Migration Service connects to your source SQL Server instance
through the Linked Server using a dedicated SQL login that you supply in the
source connection profile. You can configure this login by granting the
sysadmin server role or by configuring least-privilege permissions with the
gcp_dms_db helper database:
Grant sysadmin role
If your security policy permits granting the sysadmin server
role to the migration login, run the following T-SQL commands:
USE [master]; GO CREATE LOGIN [SOURCE_USERNAME] WITH PASSWORD = 'SOURCE_PASSWORD'; CREATE USER [SOURCE_USER] FOR LOGIN [SOURCE_USERNAME]; ALTER SERVER ROLE [sysadmin] ADD MEMBER [SOURCE_USERNAME]; GRANT CONNECT ON ENDPOINT::[HADR_ENDPOINT_NAME] TO [SOURCE_USERNAME]; GO
Replace the following:
SOURCE_USERNAMEwith the SQL login name that Database Migration Service uses to connect to your source instance (for example,cloud_dms_login).SOURCE_PASSWORDwith the password for theSOURCE_USERNAMElogin.SOURCE_USERwith the database user name mapped toSOURCE_USERNAME(for example,cloud_dms_user).HADR_ENDPOINT_NAMEwith the name of your Database Mirroring endpoint (for example,Hadr_endpoint).
Least privilege (gcp_dms_db)
If your security policy prohibits granting sysadmin to the
migration login, create the dedicated gcp_dms_db helper database
(owned by sa with TRUSTWORTHY ON), create the three
Database Migration Service wrapper stored procedures, and grant granular permissions
to your migration login:
USE [master]; GO CREATE DATABASE [gcp_dms_db]; GO ALTER AUTHORIZATION ON DATABASE::[gcp_dms_db] TO [sa]; ALTER DATABASE [gcp_dms_db] SET TRUSTWORTHY ON; GO USE [gcp_dms_db]; GO CREATE OR ALTER PROCEDURE dbo.gcp_dms_set_dag_commit_mode @dag_name NVARCHAR(128), @source_ag NVARCHAR(128), @dest_ag NVARCHAR(128), @commit_mode NVARCHAR(30) WITH EXECUTE AS 'dbo' AS BEGIN SET NOCOUNT ON; IF @commit_mode NOT IN ('SYNCHRONOUS_COMMIT', 'ASYNCHRONOUS_COMMIT') BEGIN RAISERROR('Invalid commit mode. Must be SYNCHRONOUS_COMMIT or ASYNCHRONOUS_COMMIT.', 16, 1); RETURN; END DECLARE @sql NVARCHAR(MAX); SET @sql = N'USE master; ALTER AVAILABILITY GROUP ' + QUOTENAME(@dag_name) + N' MODIFY AVAILABILITY GROUP ON ' + QUOTENAME(@source_ag, '''') + N' WITH (AVAILABILITY_MODE = ' + @commit_mode + N'), ' + QUOTENAME(@dest_ag, '''') + N' WITH (AVAILABILITY_MODE = ' + @commit_mode + N');'; EXECUTE sp_executesql @sql; END; GO CREATE OR ALTER PROCEDURE dbo.gcp_dms_set_dag_secondary @dag_name NVARCHAR(128) WITH EXECUTE AS 'dbo' AS BEGIN SET NOCOUNT ON; DECLARE @sql NVARCHAR(MAX); SET @sql = N'USE master; ALTER AVAILABILITY GROUP ' + QUOTENAME(@dag_name) + N' SET (ROLE = SECONDARY);'; EXECUTE sp_executesql @sql; END; GO CREATE OR ALTER PROCEDURE dbo.gcp_dms_failover_dag @dag_name NVARCHAR(128) WITH EXECUTE AS 'dbo' AS BEGIN SET NOCOUNT ON; DECLARE @sql NVARCHAR(MAX); SET @sql = N'USE master; ALTER AVAILABILITY GROUP ' + QUOTENAME(@dag_name) + N' FORCE_FAILOVER_ALLOW_DATA_LOSS;'; EXECUTE sp_executesql @sql; END; GO USE [master]; GO CREATE LOGIN [SOURCE_USERNAME] WITH PASSWORD = 'SOURCE_PASSWORD'; CREATE USER [SOURCE_USER] FOR LOGIN [SOURCE_USERNAME]; GRANT VIEW SERVER STATE TO [SOURCE_USERNAME]; -- Note: Run GRANT VIEW SERVER PERFORMANCE STATE on SQL Server 2022 and later: GRANT VIEW SERVER PERFORMANCE STATE TO [SOURCE_USERNAME]; GRANT VIEW ANY DEFINITION TO [SOURCE_USERNAME]; GRANT ALTER ANY AVAILABILITY GROUP TO [SOURCE_USERNAME]; GRANT CONNECT ON ENDPOINT::[HADR_ENDPOINT_NAME] TO [SOURCE_USERNAME]; GRANT CREATE CERTIFICATE TO [SOURCE_USER]; GO USE [gcp_dms_db]; GO CREATE USER [SOURCE_USER] FOR LOGIN [SOURCE_USERNAME]; GRANT EXECUTE ON dbo.gcp_dms_set_dag_commit_mode TO [SOURCE_USER]; GRANT EXECUTE ON dbo.gcp_dms_set_dag_secondary TO [SOURCE_USER]; GRANT EXECUTE ON dbo.gcp_dms_failover_dag TO [SOURCE_USER]; GO -- Repeat the following block for EACH user database in your source Availability Group: USE [DATABASE_NAME]; GO CREATE USER [SOURCE_USER] FOR LOGIN [SOURCE_USERNAME]; ALTER ROLE [db_backupoperator] ADD MEMBER [SOURCE_USER]; GO
Replace the following:
SOURCE_USERNAMEwith the SQL login name that Database Migration Service uses to connect to your source instance (for example,cloud_dms_login).SOURCE_PASSWORDwith the password for theSOURCE_USERNAMElogin.SOURCE_USERwith the database user name mapped toSOURCE_USERNAME(for example,cloud_dms_user).HADR_ENDPOINT_NAMEwith the name of your Database Mirroring endpoint (for example,Hadr_endpoint).DATABASE_NAMEwith the name of each source database in your Availability Group. Grantingdb_backupoperatoron each migrated database is required by Database Migration Service preflight verification and allows flushing transaction logs withCHECKPOINTduring promotion.
Prepare your source databases and Availability Group
You can migrate databases from an existing Always On Availability Group or
create a new standalone Availability Group (CLUSTER_TYPE = NONE). Before
continuing, verify the following requirements:
- Every database in the Availability Group uses the
FULLrecovery model, is not owned bysa, and stores its data files (.mdfand.ndf) in the default data directory. - If you reuse an existing Availability Group, confirm that your Database
Mirroring endpoint is configured on port
5022(or your chosen DBM port), thatSECONDARY_ROLE (ALLOW_CONNECTIONS = ALL)is enabled on the replica so secondary databases remain readable with standard connection strings after promotion flips the DAG roles, and that your migration login hasCONNECT ON ENDPOINT. If your source Availability Group has multiple replicas and an Availability Group listener configured, use the listener IP address as<var>SOURCE_HOST_IP_ADDRESS</var>when configuring your Linked Server and source connection profile so that the migration can resume if a failover occurs in the source Availability Group.
To prepare a database and create a new standalone Availability Group
(CLUSTER_TYPE = NONE), run the following T-SQL commands:
USE [master]; GO ALTER DATABASE [DATABASE_NAME] SET RECOVERY FULL; GO -- If the database is owned by 'sa', change the owner to another login: ALTER AUTHORIZATION ON DATABASE::[DATABASE_NAME] TO [DB_OWNER_LOGIN]; GO -- Initialize the local SQL Server transaction log chain for the Availability Group: BACKUP DATABASE [DATABASE_NAME] TO DISK = 'NUL'; GO CREATE AVAILABILITY GROUP [SOURCE_AVAILABILITY_GROUP_NAME] WITH (CLUSTER_TYPE = NONE) FOR REPLICA ON N'SOURCE_SERVER_NAME' WITH ( ENDPOINT_URL = N'TCP://localhost:SOURCE_DBM_PORT_NUMBER', FAILOVER_MODE = MANUAL, AVAILABILITY_MODE = SYNCHRONOUS_COMMIT, SEEDING_MODE = MANUAL, PRIMARY_ROLE (ALLOW_CONNECTIONS = READ_WRITE), SECONDARY_ROLE (ALLOW_CONNECTIONS = ALL) ); GO ALTER AVAILABILITY GROUP [SOURCE_AVAILABILITY_GROUP_NAME] ADD DATABASE [DATABASE_NAME]; GO
Replace the following:
DATABASE_NAMEwith the name of the database to include in your Availability Group.DB_OWNER_LOGINwith a non-salogin to own the database.SOURCE_AVAILABILITY_GROUP_NAMEwith the name of your source Availability Group (for example,source_ag).SOURCE_SERVER_NAMEwith the server name of your source SQL Server instance (matching the value returned bySELECT @@SERVERNAME).SOURCE_DBM_PORT_NUMBERwith the TCP port number of your Database Mirroring endpoint (default5022).
Establish bidirectional private network connectivity
For DAG migrations, Database Migration Service communicates with your destination Cloud SQL for SQL Server instance through internal Google Cloud APIs, executes orchestration queries on your source SQL Server instance through a Linked Server on the destination Cloud SQL for SQL Server instance, and streams data directly between the two instances over a private network. This migration requires that you establish bidirectional private IP connectivity directly between your source SQL Server host and your destination Cloud SQL for SQL Server instance through your Virtual Private Cloud network. Public IP connectivity between the source and destination instances isn't supported.
Required ports and IP addresses
Your network configuration must allow traffic between your source SQL Server instance and your destination Cloud SQL for SQL Server instance on the following two TCP ports:
| Port | Direction | Purpose |
|---|---|---|
SQL Server database port (default 1433) |
From the destination Cloud SQL for SQL Server instance to the source SQL Server instance | Used by the Linked Server on your destination Cloud SQL for SQL Server instance to run preflight validation, certificate exchange, and DAG orchestration queries on your source instance. |
Database Mirroring (DBM) port (default 5022) |
Bidirectional between the source SQL Server instance and the destination Cloud SQL for SQL Server instance | Used by the source and destination Availability Groups to stream the initial full load during FULL_DUMP, ongoing database changes during CDC, and reverse replication during FAILBACK. |
When you configure your Linked Server and connection profiles later in this guide, you provide two private IP addresses:
SOURCE_HOST_IP_ADDRESS(used in the Linked Server@datasrcparameter and the source connection profile--hostflag) is the private IP address of your source SQL Server host (or the Availability Group listener IP address, which is preferred if configured for a multi-replica source Availability Group so the migration can resume if a failover occurs in the source Availability Group) that is reachable from your destination Cloud SQL for SQL Server instance.DESTINATION_HOST_IP_ADDRESS(used in the destination connection profile--hostflag) is the private IP address of your destination Cloud SQL for SQL Server instance (or its Private Service Connect endpoint IP address) that is reachable from your source SQL Server host.
Configure your private networking method
Complete the network routing configuration for the networking method (Private Services Access or Private Service Connect) that you enabled on your destination Cloud SQL for SQL Server instance:
Private Services Access
Private Services Access peers your Virtual Private Cloud network with the Google-managed service producer Virtual Private Cloud network that hosts your destination Cloud SQL for SQL Server instance:
- Verify that your Virtual Private Cloud network has an allocated internal IPv4
address range and a private connection (Virtual Private Cloud peering to
servicenetworking-googleapis-com) enabled for your destination Cloud SQL for SQL Server instance. For instructions, see Configure private IP for Cloud SQL for SQL Server. - Configure routing to your source SQL Server host based on
where it is hosted:
- If your source instance runs on a Compute Engine virtual machine in the same Virtual Private Cloud network, no additional routing is required. The virtual machine and the Cloud SQL for SQL Server instance can reach each other's private IP addresses directly over the Virtual Private Cloud peering connection.
- If your source instance runs on-premises, in another cloud provider,
or in another Virtual Private Cloud network, complete the following steps so that
routes are exchanged across the transitive peering boundary:
- Connect your external network to your Virtual Private Cloud network by using Cloud VPN or Cloud Interconnect. For instructions, see Access a Cloud SQL instance from an external source.
- In Cloud Router, advertise the Cloud SQL for SQL Server allocated IP address range to your source network. For instructions, see Advertise custom IP ranges.
- Update the
servicenetworking-googleapis-compeering connection in your Virtual Private Cloud network to enable Export custom routes so that your Cloud SQL for SQL Server instance learns the routes to your source network. For instructions, see Update a peering connection.
- Record the private IP addresses for your migration:
- Use your source SQL Server host's internal IP address as
SOURCE_HOST_IP_ADDRESS. - Use the Private IP address assigned to your destination
Cloud SQL for SQL Server instance (shown on the instance Overview page)
as
DESTINATION_HOST_IP_ADDRESS.
- Use your source SQL Server host's internal IP address as
Private Service Connect
If you use
Private Service Connect
instead of Private Services Access, you must configure both an inbound
Private Service Connect endpoint (so your source instance can connect
to Cloud SQL for SQL Server on port 5022) and an outbound
Private Service Connect interface (so Cloud SQL for SQL Server can
initiate Linked Server and DAG connections to your source instance on ports
1433 and 5022):
- Verify that your destination Cloud SQL for SQL Server instance has Private Service Connect enabled (without Private IP) and specifies your allowed consumer projects. For instructions, see Configure Private Service Connect.
- To allow inbound connections from your source SQL Server host to your destination Cloud SQL for SQL Server instance, reserve an internal IP address in your Virtual Private Cloud subnet and create a Private Service Connect endpoint (forwarding rule) that targets your Cloud SQL for SQL Server instance's service attachment. For instructions, see Create a Private Service Connect endpoint.
- To allow outbound connections from your destination Cloud SQL for SQL Server instance to your source SQL Server host (required for Linked Server and outbound DAG connections), create a Virtual Private Cloud network attachment in the subnet that can route to your source host and configure Private Service Connect outbound connectivity on your destination Cloud SQL for SQL Server instance. For instructions, see Create and manage network attachments and Configure Private Service Connect outbound connectivity.
- Record the private IP addresses for your migration:
- Use your source SQL Server host's private IP address as
SOURCE_HOST_IP_ADDRESS. - Use the internal IP address of your
Private Service Connect endpoint (forwarding rule) in your
Virtual Private Cloud network as
DESTINATION_HOST_IP_ADDRESS.
- Use your source SQL Server host's private IP address as
Configure Virtual Private Cloud and source host firewall rules
- In your Virtual Private Cloud network, create ingress and egress firewall rules that
allow TCP traffic between your source SQL Server IP address
(
SOURCE_HOST_IP_ADDRESS) and your destination Cloud SQL for SQL Server IP range (or Private Service Connect endpoint and network attachment subnet) on both the database port (default1433) and the Database Mirroring port (default5022). For more information about creating firewall rules, see Create firewall rules. - On your source SQL Server machine, verify the following network and
host firewall settings:
- TCP/IP is enabled in SQL Server Configuration Manager (or
mssql-confon Linux) and the instance listens on a static TCP port (default1433). - The operating system firewall (such as Windows Defender Firewall or Linux
iptablesorfirewalld) allows inbound TCP connections on both your database port (default1433) and your Database Mirroring port (default5022), and outbound TCP connections toDESTINATION_HOST_IP_ADDRESSon port5022.
- TCP/IP is enabled in SQL Server Configuration Manager (or
Verify reachability with Cloud SQL connectivity tests
Before you configure your Linked Server, we recommend running three connectivity tests from the Connections > Connectivity tests tab of your Cloud SQL for SQL Server instance in the Google Cloud console. For instructions on how to run a connectivity test, see Manage connectivity tests:
- To test outbound Linked Server connectivity on port
1433, set Source to Current Cloud SQL instance, Destination toSOURCE_HOST_IP_ADDRESS, and Destination port to1433(or your custom database port). - To test outbound Database Mirroring connectivity on port
5022, set Source to Current Cloud SQL instance, Destination toSOURCE_HOST_IP_ADDRESS, and Destination port to5022(or your customDBMport). - To test inbound Database Mirroring connectivity on port
5022, set Source toSOURCE_HOST_IP_ADDRESS, Destination to Current Cloud SQL instance (orDESTINATION_HOST_IP_ADDRESSif you use Private Service Connect), and Destination port to5022(or your customDBMport).
Create and verify the Linked Server on your destination Cloud SQL for SQL Server instance
After your network connectivity is in place, connect to your destination Cloud SQL for SQL Server instance and create the Linked Server pointing to your source SQL Server instance:
- Connect to your Cloud SQL instance with a SQL client. You can use the
following methods:
sqlcmdclient. You can use this method to connect to your instance private IP, but it might require that you create a Compute Engine virtual machine.gcloud sql connectcommand. This command works only for Cloud SQL instances that have a public IP address enabled.
- Sign in as the
sqlserveruser and run the following T-SQL commands for your destination Cloud SQL for SQL Server version to create a Linked Server pointing to your source SQL Server instance, map@locallogin = N'sqlserver'to your source migration login, enablerpc out, and test the connection withOPENQUERY(for more information about Linked Server options on Cloud SQL, see Manage linked servers):Cloud SQL for SQL Server 2017, 2019, and 2022
USE [master]; GO EXEC master.dbo.sp_addlinkedserver @server = N'LINKED_SERVER_NAME', @srvproduct = N'', @provider = N'SQLNCLI', @datasrc = N'SOURCE_HOST_IP_ADDRESS,SOURCE_PORT_NUMBER'; GO EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname = N'LINKED_SERVER_NAME', @useself = N'False', @locallogin = N'sqlserver', @rmtuser = N'SOURCE_USERNAME', @rmtpassword = N'SOURCE_PASSWORD'; GO EXEC master.dbo.sp_serveroption @server = N'LINKED_SERVER_NAME', @optname = N'rpc out', @optvalue = N'TRUE'; GO SELECT * FROM OPENQUERY([LINKED_SERVER_NAME], 'SELECT @@VERSION AS SourceServerVersion'); GO
Cloud SQL for SQL Server 2025
USE [master]; GO EXEC master.dbo.sp_addlinkedserver @server = N'LINKED_SERVER_NAME', @srvproduct = N'', @provider = N'MSOLEDBSQL19', @datasrc = N'SOURCE_HOST_IP_ADDRESS,SOURCE_PORT_NUMBER', @provstr = N'Encrypt=Optional;TrustServerCertificate=Yes;Authentication=SqlPassword;UID=Placeholder;'; GO EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname = N'LINKED_SERVER_NAME', @useself = N'False', @locallogin = N'sqlserver', @rmtuser = N'SOURCE_USERNAME', @rmtpassword = N'SOURCE_PASSWORD'; GO EXEC master.dbo.sp_serveroption @server = N'LINKED_SERVER_NAME', @optname = N'rpc out', @optvalue = N'TRUE'; GO SELECT * FROM OPENQUERY([LINKED_SERVER_NAME], 'SELECT @@VERSION AS SourceServerVersion'); GO
Replace the following:
LINKED_SERVER_NAMEwith the name for your Linked Server on Cloud SQL for SQL Server (for example,source_sql_linked_server).SOURCE_HOST_IP_ADDRESSwith the private IP address of your source SQL Server instance (or the Availability Group listener IP address if configured for a multi-replica source Availability Group).SOURCE_PORT_NUMBERwith the port number where your source SQL Server database engine accepts connections (default1433).SOURCE_USERNAMEwith the dedicated SQL login name that you created on your source instance in Create the dedicated Database Migration Service login and permissions.SOURCE_PASSWORDwith the password for theSOURCE_USERNAMElogin.
Create connection profiles and run the migration job
Use the Google Cloud CLI to create the source and destination connection profiles, create the continuous DAG migration job, verify the migration configuration, and start the migration job:
-
Create the source connection profile.
Run thegcloud database-migration connection-profiles create sqlservercommand (click to expand):gcloud database-migration connection-profiles create sqlserverThis sample uses the optional
--no-asyncflag so that all operations are performed synchronously. This means that some commands might take a while to complete. You can skip the--no-asyncflag to run commands asynchronously. If you do, you need to use thegcloud database-migration operations describecommand to verify if your operation is successful.gcloud database-migration connection-profiles create sqlserver SOURCE_CONNECTION_PROFILE_ID \ --no-async \ --display-name=SOURCE_CONNECTION_PROFILE_NAME \ --region=REGION \ --role=SOURCE \ --host=SOURCE_HOST_IP_ADDRESS \ --port=SOURCE_PORT_NUMBER \ --dbm-port=SOURCE_DBM_PORT_NUMBER \ --username=SOURCE_USERNAME \ --password=SOURCE_PASSWORD
Replace the following:
SOURCE_CONNECTION_PROFILE_IDwith a machine-readable identifier for your source connection profile (for example,sqlserver-dag-source-profile).SOURCE_CONNECTION_PROFILE_NAMEwith a human-readable name for your source connection profile. This value is displayed in Database Migration Service in the Google Cloud console.REGIONwith the identifier of the region where you want to save the connection profile (for example,us-central1).SOURCE_HOST_IP_ADDRESSwith the private IP address of your source SQL Server instance (or the Availability Group listener IP address if configured for a multi-replica source Availability Group).SOURCE_PORT_NUMBERwith the port number where your source SQL Server database engine accepts connections (default1433).SOURCE_DBM_PORT_NUMBERwith the TCP port number of your source Database Mirroring endpoint (default5022).SOURCE_USERNAMEwith the dedicated SQL login name that you created on your source instance in Create the dedicated Database Migration Service login and permissions.SOURCE_PASSWORDwith the password for theSOURCE_USERNAMElogin.
-
Create the destination connection profile.
Run thegcloud database-migration connection-profiles create sqlservercommand (click to expand):gcloud database-migration connection-profiles create sqlserverThis sample uses the optional
--no-asyncflag so that all operations are performed synchronously. This means that some commands might take a while to complete. You can skip the--no-asyncflag to run commands asynchronously. If you do, you need to use thegcloud database-migration operations describecommand to verify if your operation is successful.gcloud database-migration connection-profiles create sqlserver DESTINATION_CONNECTION_PROFILE_ID \ --no-async \ --display-name=DESTINATION_CONNECTION_PROFILE_NAME \ --region=REGION \ --role=DESTINATION \ --cloudsql-instance=CLOUDSQL_INSTANCE_ID \ --host=DESTINATION_HOST_IP_ADDRESS \ --port=DESTINATION_PORT_NUMBER \ --dbm-port=DESTINATION_DBM_PORT_NUMBER \ --username=sqlserver \ --password=CLOUD_SQL_DB_USER_PASSWORD
Replace the following:
DESTINATION_CONNECTION_PROFILE_IDwith a machine-readable identifier for your destination connection profile (for example,sqlserver-dag-dest-profile).DESTINATION_CONNECTION_PROFILE_NAMEwith a human-readable name for your destination connection profile. This value is displayed in Database Migration Service in the Google Cloud console.REGIONwith the identifier of the region where you want to save the connection profile.CLOUDSQL_INSTANCE_IDwith the name of your destination Cloud SQL for SQL Server instance.DESTINATION_HOST_IP_ADDRESSwith the private IP address of your destination Cloud SQL for SQL Server instance (or its Private Service Connect endpoint IP address) as reachable from your source SQL Server instance.DESTINATION_PORT_NUMBERwith the database port number of your destination Cloud SQL for SQL Server instance (1433).DESTINATION_DBM_PORT_NUMBERwith the Database Mirroring port number of your destination Cloud SQL for SQL Server instance (5022).CLOUD_SQL_DB_USER_PASSWORDwith the password for thesqlserveruser on your destination Cloud SQL for SQL Server instance (--usernamemust be set tosqlserver).
-
Create the continuous DAG migration job.
Run thegcloud database-migration migration-jobs createcommand (click to expand):gcloud database-migration migration-jobs createThis sample uses the optional
--no-asyncflag so that all operations are performed synchronously. This means that some commands might take a while to complete. You can skip the--no-asyncflag to run commands asynchronously. If you do, you need to use thegcloud database-migration operations describecommand to verify if your operation is successful.gcloud database-migration migration-jobs create MIGRATION_JOB_ID \ --no-async \ --display-name=MIGRATION_JOB_NAME \ --region=REGION \ --type=CONTINUOUS \ --source=SOURCE_CONNECTION_PROFILE_ID \ --destination=DESTINATION_CONNECTION_PROFILE_ID \ --sqlserver-dag-source-ag=SOURCE_AVAILABILITY_GROUP_NAME \ --sqlserver-dag-linked-server=LINKED_SERVER_NAME
Replace the following:
MIGRATION_JOB_IDwith a machine-readable identifier for your migration job (for example,sqlserver-dag-job).MIGRATION_JOB_NAMEwith a human-readable name for your migration job. This value is displayed in the Google Cloud console.REGIONwith the identifier of the region where you want to create the migration job.SOURCE_CONNECTION_PROFILE_IDwith the identifier of your source connection profile.DESTINATION_CONNECTION_PROFILE_IDwith the identifier of your destination connection profile.SOURCE_AVAILABILITY_GROUP_NAMEwith the name of the Availability Group on your source SQL Server instance.LINKED_SERVER_NAMEwith the name of the Linked Server that you configured on your destination Cloud SQL for SQL Server instance in Create and verify the Linked Server on your destination Cloud SQL for SQL Server instance.
-
Verify the migration job configuration.
Before starting a DAG migration job, you must runverifyto validate bidirectional network connectivity, Linked Server RPC access,gcp_dms_dbpermissions (if using least privilege), source database owners (verifying that no database is owned bysa), and default data file paths. Run thegcloud database-migration migration-jobs verifycommand (click to expand):gcloud database-migration migration-jobs verifygcloud database-migration migration-jobs verify MIGRATION_JOB_ID \ --region=REGION
Replace the following:
MIGRATION_JOB_IDwith the identifier of your migration job.REGIONwith the identifier of the region where the migration job is saved.
You can check the status of the verification operation by running the
gcloud database-migration operations describecommand. -
Start the migration job.
After verification succeeds, run thegcloud database-migration migration-jobs startcommand (click to expand):gcloud database-migration migration-jobs startgcloud database-migration migration-jobs start MIGRATION_JOB_ID \ --region=REGION
Replace the following:
MIGRATION_JOB_IDwith the identifier of your migration job.REGIONwith the identifier of the region where the migration job is saved.
Monitor and verify your migration
While the DAG migration job is running, you can monitor its progress in
the Google Cloud console, query your destination databases in read-only mode
during CDC, and manage active replication.
Monitor progress in the Google Cloud console
You can monitor a running DAG migration job in the Google Cloud console on the Migration job details page, just like other Database Migration Service migration jobs:
- In the Databases table on the migration job details page, view the
real-time phase (
Full dumpduring the initial full load,CDCduring continuous replication, and any database-level error messages) and Restore lag for each database in your Availability Group. - In the Monitoring tab, view the Restore lag
(
datamigration.googleapis.com/migration_job/max_replica_sec_lag, which reports the Distributed Availability Group replication lag in seconds per database) chart.
For more information about monitoring metrics and job states, see Migration job metrics and Migration job status codes.
Verify migrated databases in read-only mode during CDC
Unlike backup-based migrations (where destination databases remain in the
RESTORING state until promotion), Distributed Availability Group migrations
allow you to query your destination Cloud SQL for SQL Server databases in
read-only mode as soon as they enter the CDC phase.
For each database owned by a SQL login on the source instance,
Database Migration Service automatically creates a login on the destination
Cloud SQL for SQL Server instance prefixed with gcp_dms_, a 6-character
identifier, and the source owner name (for example, gcp_dms_a1b2c3_myowner).
To query the database with that login before promotion, connect to your
destination Cloud SQL for SQL Server instance as sqlserver, find the generated
login name in sys.server_principals, and reset its password:
SELECT name FROM sys.server_principals WHERE name LIKE 'gcp_dms_%'; GO ALTER LOGIN [GENERATED_DMS_OWNER_LOGIN] WITH PASSWORD = 'NEW_OWNER_PASSWORD'; GO
Replace the following:
GENERATED_DMS_OWNER_LOGINwith the generated database owner login name returned by the query.NEW_OWNER_PASSWORDwith a new password for the login.
For more information about verifying migrated objects and data, see Verify a migration.
Manage an active DAG migration job (Optional)
While your migration job is running in the CDC phase, you can perform the
following management operations:
- Add or remove databases in your source Availability Group on your source
SQL Server instance by running
ALTER AVAILABILITY GROUP ... ADD DATABASEorALTER AVAILABILITY GROUP ... REMOVE DATABASE. Database Migration Service automatically detects the change on its next polling cycle and updates the destination Cloud SQL for SQL Server instance. - Temporarily halt data replication by running
gcloud database-migration migration-jobs stop. Stopping a DAG migration job should only be used for a defined, short period, because updates continue to accumulate in the transaction logs while replication is halted and can cause transaction log disks to fill up. From a stopped state, you can either rungcloud database-migration migration-jobs resumeto resume data replication, or rungcloud database-migration migration-jobs deleteto complete the migration and perform the necessary cleanup. - Restart a failed migration job by running
gcloud database-migration migration-jobs restart. Restarting a DAG migration job deletes the migrated databases on your destination Cloud SQL for SQL Server instance, recreates the Distributed Availability Group, and re-runs the initial full load over the network.
Promote, fail back, or complete the migration
When you are ready to switch your applications to Cloud SQL for SQL Server, promote
the migration job. In a DAG migration, promoting the job switches
Cloud SQL for SQL Server to the read/write Primary and transitions the migration job
into the FAILBACK phase (PHASE_FAILBACK in Google Cloud CLI and API
responses) with active reverse replication back to your source
SQL Server instance:
- Stop application writes to your source SQL Server databases and check the Restore lag metric in the Google Cloud console to confirm that replication lag has reached zero.
-
Promote the migration job to cut over to Cloud SQL.
Run thegcloud database-migration migration-jobs promotecommand (click to expand):gcloud database-migration migration-jobs promotegcloud database-migration migration-jobs promote MIGRATION_JOB_ID \ --region=REGION
Replace the following:
MIGRATION_JOB_IDwith the identifier of your migration job.REGIONwith the identifier of the region where the migration job is saved.
During promotion, Database Migration Service performs the following actions:
- Sets the Distributed Availability Group to synchronous commit, issues a
CHECKPOINTon all source databases, waits for all transactions to synchronize with zero data loss, and reverses the Availability Group roles so your destination Cloud SQL for SQL Server instance becomes the read/write Primary and your original source SQL Server instance becomes the Secondary. - Keeps the migration job in the
Runningstate and transitions the substate to theFAILBACKphase (PHASE_FAILBACKin Google Cloud CLI and API responses), continuously replicating new writes from your destination Cloud SQL for SQL Server back to the source SQL Server instance.
After promotion completes, connect your applications to your new Cloud SQL for SQL Server instance.
-
(Optional) Fail back to your source SQL Server instance.
If you encounter an issue after switching your applications to Cloud SQL for SQL Server while the migration job is in theFAILBACKphase, you can revert the cutover with zero data loss by stopping application writes on Cloud SQL for SQL Server and running thegcloud database-migration migration-jobs promotecommand with the--failbackflag (click to expand):gcloud database-migration migration-jobs promote --failbackgcloud database-migration migration-jobs promote MIGRATION_JOB_ID \ --region=REGION \ --failback
Replace the following:
MIGRATION_JOB_IDwith the identifier of your migration job.REGIONwith the identifier of the region where the migration job is saved.
Running
promotewith the--failbackflag during theFAILBACKphase synchronizes all changes written to Cloud SQL for SQL Server, switches the replication direction again so your original source SQL Server Availability Group becomes the read/write Primary and Cloud SQL for SQL Server becomes the Secondary, and returns the migration job to theCDCphase. Note that--failbackis valid only when the migration job is in theFAILBACKphase; runningpromotewithout--failbackduring theFAILBACKphase (or passing--failbackduring theCDCphase) fails validation with aFAILED_PRECONDITIONerror and leaves the migration job running. -
(Optional) Stop data replication before deleting the migration job.
If you want to halt data replication before permanently deleting the migration job, run thegcloud database-migration migration-jobs stopcommand (click to expand):gcloud database-migration migration-jobs stopgcloud database-migration migration-jobs stop MIGRATION_JOB_ID \ --region=REGION
Replace the following:
MIGRATION_JOB_IDwith the identifier of your migration job.REGIONwith the identifier of the region where the migration job is saved.
-
Complete the migration and delete the migration job.
Once you verify that your applications are fully operational with the new Cloud SQL for SQL Server destination instance, and you no longer need reverse replication to the source SQL Server instance, delete the migration job (from either theRunningorStoppedstate) to complete the migration and perform the necessary cleanup. Run thegcloud database-migration migration-jobs deletecommand (click to expand):gcloud database-migration migration-jobs deleteThis command returns an interactive confirmation prompt that requires your input to complete. You can skip the confirmation prompt by using the optional
--quietflag.gcloud database-migration migration-jobs delete MIGRATION_JOB_ID \ --region=REGION
Replace the following:
MIGRATION_JOB_IDwith the identifier of your migration job.REGIONwith the identifier of the region where the migration job is saved.
Deleting the migration job completes the migration, stops any active reverse replication, drops the Distributed Availability Group and Database Mirroring certificates on both instances, and lets you enable Cloud SQL for SQL Server features that are restricted during DAG replication (such as Point-in-time recovery (PITR) or read replicas).
After you delete the migration job, you can optionally disable or remove the
cloud sql enable dag supportdatabase flag on your destination Cloud SQL for SQL Server instance, drop the Linked Server on your Cloud SQL for SQL Server instance (EXEC master.dbo.sp_dropserver @server = N'LINKED_SERVER_NAME', @droplogins = 'droplogins';), and remove thegcp_dms_dbhelper database and migration login on your source SQL Server instance.