通过


你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

使用脚本进行链接配置 - Azure SQL 托管实例

applies to:Azure SQL 托管实例

本文介绍如何使用 Transact-SQL 和 PowerShell 或 Azure CLI 脚本在SQL Server和Azure SQL 托管实例之间配置 link。 通过该链接,初始主要副本中的数据库将近乎实时地复制到次要副本。

创建链接后,可以故障转移到次要副本以进行迁移或灾难恢复。

注意

概述

使用链接功能将初始主要副本中的数据库复制到次要副本。 对于 2022 SQL Server,初始主数据库可以是SQL Server或Azure SQL 托管实例。 对于 SQL Server 2019 和早期版本,初始主数据库必须SQL Server。 配置链接后,将初始主要副本中的数据库复制到次要副本。

可以选择在主副本和次要副本之间的混合环境中保留用于连续数据复制的链接,或者可以将数据库故障转移到次要副本、迁移到 Azure,或用于灾难恢复。 对于 SQL Server 2019 和更早版本,故障转移到 Azure SQL 托管实例会中断链接,不支持故障回复操作。 使用 SQL Server 2022,您可以选择保持连接,并在两个副本之间来回切换以处理故障。

如果计划仅使用辅助托管实例进行灾难恢复,可以通过激活混合故障转移权益来节省许可成本。

使用本文中的说明手动设置SQL Server和Azure SQL 托管实例之间的链接。 创建链接后,源数据库的只读副本会在您目标的次要副本上被创建。

提示

为了简化使用适合您环境的正确参数的 T-SQL 脚本,我们强烈建议在 SQL Server Management Studio (SSMS) 中使用 托管实例 链接向导生成用于创建链接的脚本。 在Summary页上的新的托管实例链接窗口中,选择Script而不是Finish

先决条件

若要复制数据库,需要满足以下先决条件:

考虑以下情况:

  • 链接功能支持每个链接有一个数据库。 若要在一个实例上复制多个数据库,请为每个单独的数据库创建一个链接。 例如,若要将 10 个数据库复制到SQL 托管实例,请创建 10 个单独的链接。
  • SQL Server和SQL 托管实例之间的排序规则应相同。 排序规则不匹配可能会导致服务器名称大小写不匹配,并阻止成功连接SQL Server到SQL 托管实例。
  • 初始SQL Server主副本上的错误 1475 指示需要通过创建完整备份来启动新的备份链,而无需使用 COPY ONLY 选项。
  • 若要建立链接或故障转移,从 SQL 托管实例到 SQL Server 2025,必须将 SQL 托管实例配置为使用 SQL Server 2025 更新策略。 配置了不匹配更新策略的实例不支持从 SQL 托管实例到 SQL Server 2025 的数据复制和故障转移。
  • 若要建立链接或故障转移,从 SQL 托管实例到 SQL Server 2022,您的 SQL 托管实例必须配置为使用 SQL Server 2022 更新策略。 对于配置了不匹配更新策略的实例,不支持数据复制和故障转移SQL 托管实例 到 SQL Server 2022。
  • 虽然可以建立从受支持的 SQL Server 版本到使用 Always-up-to-date 更新策略配置的 SQL 托管实例的链接,但在故障转移到 SQL 托管实例后,将无法再复制数据或故障回复到您的 SQL Server 实例。

权限

对于 SQL Server,应具有 sysadmin 权限。

对于Azure SQL 托管实例,应是SQL 托管实例参与者的成员,或者具有以下自定义角色权限:

Microsoft.Sql/资源 必要的权限
Microsoft/Sql/managedInstances /read、/write
Microsoft.Sql/managedInstances/hybridCertificate /action
Microsoft。Sql/managedInstances/databases /read、/delete、/write、/completeRestore/action、/readBackups/action、/restoreDetails/read
Microsoft。Sql/managedInstances/distributedAvailabilityGroups /read、/write、/delete、/setRole/action
Microsoft。Sql/managedInstances/endpointCertificates /read
Microsoft.Sql/managedInstances/hybridLink /read、/write、/delete
Microsoft。Sql/managedInstances/serverTrustCertificates /write、/delete、/read

术语和命名约定

从本用户指南中运行脚本时,请务必不要将 SQL Server 和 SQL 托管实例 的名称误认为它们的完全限定域名(FQDN)。 下表说明了各种名称确切表示的内容,以及如何获取其值:

术语 说明 如何找出
初始主 1 最初在 SQL Server 或 SQL 托管实例 上创建链接,以将您的数据库复制到次要副本。
主要副本 当前托管主数据库的SQL Server或SQL 托管实例。
次级副本 从当前主副本接收近实时复制数据的 SQL Server 或 SQL 托管实例。
SQL Server名称 短单字SQL Server名称。 例如:“sqlserver1”。 通过 T-SQL 运行 SELECT @@SERVERNAME
SQL Server FQDN 您的 SQL Server 的完全限定域名 (FQDN)。 例如:“sqlserver1.domain.com”。 如果使用的是Azure虚拟机(VM),请参阅本地网络(DNS)配置或服务器名称。
SQL 托管实例 名称 短单字SQL 托管实例名称。 例如:“managedinstance1”。 在 Azure 门户中查看托管实例的名称。
SQL 托管实例 FQDN (完全限定域名) SQL 托管实例的完全限定域名 (FQDN)。 例如:“managedinstance1.6d710bcf372b.database.windows.net”。 请参阅Azure门户中SQL 托管实例概述页上的主机名。
可解析域名 可解析为 IP 地址的 DNS 名称。 例如,运行 nslookup sqlserver1.domain.com 应返回一个 IP 地址,例如 10.0.0.1。 通过命令提示符运行 nslookup 命令。
SQL Server IP SQL Server的 IP 地址。 对于SQL Server上的多个 IP,请选择可从Azure访问的 IP 地址。 从运行SQL Server的主机 OS 的命令提示符运行 ipconfig 命令。

1 支持从 SQL Server 2022 CU10 开始将 Azure SQL 托管实例配置为初始主数据库。

设置数据库恢复和备份

如果SQL Server是初始主数据库,则通过链接复制的数据库必须位于完整恢复模式下,并且至少有一个备份。 由于Azure SQL 托管实例自动执行备份,因此如果SQL 托管实例是初始主数据库,请跳过此步骤。

创建链接时,主要副本和次要副本之间的初始种子设定是通过在主副本上对数据库进行完整备份、将其传输到次要副本以及还原到该副本而进行的。 执行完整备份时,建议使用 WITH CHECKSUM 此选项来确保备份有效且没有任何损坏。 有关详细信息,请参阅 BACKUP (Transact-SQL)

针对要复制的所有数据库SQL Server运行以下代码。 将 <DatabaseName> 替换为数据库的实际名称。

-- Run on SQL Server
-- Set full recovery model for all databases you want to replicate.
ALTER DATABASE [<DatabaseName>] SET RECOVERY FULL
GO

-- Execute backup for all databases you want to replicate.
BACKUP DATABASE [<DatabaseName>] TO DISK = N'<DiskPath>'
GO

有关详细信息,请参阅创建完整数据库备份

注意

该链接仅支持复制用户数据库。 不支持复制系统数据库。 要复制实例级对象(存储在 mastermsdb 数据库中),我们建议编写 T-SQL 脚本,并在目标实例上运行这些脚本。

在实例之间建立信任

首先,必须在两个实例之间建立信任,并保护用于在网络上进行数据通信和加密的终结点。 分布式可用性组使用现有的可用性组数据库镜像终结点,而不是使用自己的专用终结点。 因此需要通过可用性组数据库镜像终结点在两个实例之间配置安全性和信任。

注意

此链接基于 Always On 可用性组技术。 数据库镜像终结点是用途特殊的终结点,专门由可用性组接收来自其他实例的连接。 术语“数据库镜像端点”不应与旧版 SQL Server 数据库镜像功能混淆。

基于证书的信任是保护SQL Server和SQL 托管实例数据库镜像终结点的唯一支持方法。 如果已经有使用Windows身份验证的可用性组,则需要在现有的镜像终结点中添加基于证书的信任,以用作辅助身份验证选项。 可以使用 ALTER ENDPOINT 语句来执行此操作,如本文后面部分所示。

重要

生成的证书有过期日期和时间。 证书需要在过期之前进行续订和轮换。

下面概述了保护SQL Server和SQL 托管实例的数据库镜像终结点的过程:

  1. 在SQL Server上生成证书并获取其公钥。
  2. 获取SQL 托管实例证书的公钥。
  3. 交换 SQL Server 和 SQL 托管实例 之间的公钥。
  4. 将受信任的根证书颁发机构密钥导入到 Azure SQL Server

以下各部分详细介绍了这些步骤。

在SQL Server上创建证书并将其公钥导入到SQL 托管实例

首先,在 master 数据库中创建数据库主密钥(如果尚不存在)。 在下面的脚本中插入密码替代 <strong_password>,并将其保存在机密且安全的地方。 在SQL Server上运行此 T-SQL 脚本:

-- Run on SQL Server
-- Create a master key encryption password
-- Keep the password confidential and in a secure place
USE MASTER
IF NOT EXISTS (SELECT * FROM sys.symmetric_keys WHERE symmetric_key_id = 101)
BEGIN
    PRINT 'Creating master key.' + CHAR(13) + 'Keep the password confidential and in a secure place.'
    CREATE MASTER KEY ENCRYPTION BY PASSWORD = '<strong_password>'
END
ELSE
    PRINT 'Master key already exists.'
GO

然后,在SQL Server生成身份验证证书。 在以下代码中,进行以下替换:

  • @cert_expiry_date 替换为所需证书到期日期(未来日期)。

记录此日期并设置提醒,以便在 SQL 服务器证书到期前进行轮换(更新),从而确保链接持续运行。

重要

强烈建议使用此脚本中自动生成的证书名称。 允许在SQL Server上自定义自己的证书名称时,该名称不应包含任何\字符。

-- Create the SQL Server certificate for the instance link
USE MASTER

-- Customize SQL Server certificate expiration date by adjusting the date below
DECLARE @cert_expiry_date AS varchar(max)='03/30/2025'

-- Build the query to generate the certificate
DECLARE @sqlserver_certificate_name NVARCHAR(MAX) = N'Cert_' + @@servername  + N'_endpoint'
DECLARE @sqlserver_certificate_subject NVARCHAR(MAX) = N'Certificate for ' + @sqlserver_certificate_name
DECLARE @create_sqlserver_certificate_command NVARCHAR(MAX) = N'CREATE CERTIFICATE [' + @sqlserver_certificate_name + '] ' + char (13) +
'    WITH SUBJECT = ''' + @sqlserver_certificate_subject + ''',' + char (13) +
'    EXPIRY_DATE = '''+ @cert_expiry_date + ''''+ char (13)
IF NOT EXISTS (SELECT name from sys.certificates WHERE name = @sqlserver_certificate_name)
BEGIN
    PRINT (@create_sqlserver_certificate_command)
    -- Execute the query to create SQL Server certificate for the instance link
    EXEC sp_executesql @stmt = @create_sqlserver_certificate_command
END
ELSE
    PRINT 'Certificate ' + @sqlserver_certificate_name + ' already exists.'
GO

然后,对SQL Server使用以下 T-SQL 查询来验证是否已创建证书:

-- Run on SQL Server
USE MASTER
GO
SELECT * FROM sys.certificates WHERE pvt_key_encryption_type = 'MK'

在查询结果中,你将看到该证书已用主密钥进行了加密。

现在,可以在SQL Server上获取生成的证书的公钥:

-- Run on SQL Server
-- Show the name and the public key of generated SQL Server certificate
USE MASTER
GO
DECLARE @sqlserver_certificate_name NVARCHAR(MAX) = N'Cert_' + @@servername  + N'_endpoint'
DECLARE @PUBLICKEYENC VARBINARY(MAX) = CERTENCODED(CERT_ID(@sqlserver_certificate_name));
SELECT @sqlserver_certificate_name as 'SQLServerCertName'
SELECT @PUBLICKEYENC AS SQLServerPublicKey;

保存来自输出的 SQLServerCertNameSQLServerPublicKey 的值,因为导入证书的下一步需要用到。

首先,请确保已登录到 Azure,并且已选择在其中托管你的托管实例的订阅。 如果帐户上有多个Azure订阅,则选择适当的订阅尤其重要。

<SubscriptionID> 替换为Azure订阅 ID。

# Run in Azure Cloud Shell (select PowerShell console)

# Enter your Azure subscription ID
$SubscriptionID = "<SubscriptionID>"

# Login to Azure and select subscription ID
if ((Get-AzContext ) -eq $null)
{
    echo "Logging to Azure subscription"
    Login-AzAccount
}
Select-AzSubscription -SubscriptionName $SubscriptionID

然后使用 New-AzSqlInstanceServerTrustCertificate PowerShell 或 az sql mi partner-cert create Azure CLI 命令将身份验证证书的公钥从 SQL Server 上传到 Azure,例如以下 PowerShell 示例。

填写必要的用户信息,复制、粘贴信息,然后运行脚本。 替换:

  • <SQLServerPublicKey>,其中包含以二进制格式表示的、在上一步中记录的 SQL Server 证书的公共部分。 它是以 0x 开头的长字符串值。
  • <SQLServerCertName>,其中包含在上一步中记录的SQL Server证书名称。
  • <ManagedInstanceName> 替换为你的托管实例的短名称。
# Run in Azure Cloud Shell (select PowerShell console)
# ===============================================================================
# POWERSHELL SCRIPT TO IMPORT SQL SERVER PUBLIC CERTIFICATE TO SQL MANAGED INSTANCE
# ===== Enter user variables here ====

# Enter the name for the server SQLServerCertName certificate – for example, "Cert_sqlserver1_endpoint"
$CertificateName = "<SQLServerCertName>"

# Insert the certificate public key blob that you got from SQL Server – for example, "0x1234567..."
$PublicKeyEncoded = "<SQLServerPublicKey>"

# Enter your managed instance short name – for example, "sqlmi"
$ManagedInstanceName = "<ManagedInstanceName>"

# ==== Do not customize the below cmdlets====

# Find out the resource group name
$ResourceGroup = (Get-AzSqlInstance -InstanceName $ManagedInstanceName).ResourceGroupName

# Upload the public key of the authentication certificate from SQL Server to Azure.
New-AzSqlInstanceServerTrustCertificate -ResourceGroupName $ResourceGroup -InstanceName $ManagedInstanceName -Name $CertificateName -PublicKey $PublicKeyEncoded 

此操作的结果是上传SQL Server证书到Azure的摘要。

如果需要查看所有上传到托管实例的SQL Server证书,请使用 Azure Cloud Shell 中的 Get-AzSqlInstanceServerTrustCertificate PowerShell 或 az sql mi partner-cert list Azure CLI 命令。 若要删除上传到 SQL 托管实例的SQL Server证书,请使用 Azure Cloud Shell 中的 Remove-AzSqlInstanceServerTrustCertificate PowerShell 或 az sql mi partner-cert delete Azure CLI 命令。

从SQL 托管实例获取证书公钥并将其导入到SQL Server

用于保护链接终结点的证书在Azure SQL 托管实例上自动生成。 从 SQL 托管实例 获取证书公钥,并使用 Get-AzSqlInstanceEndpointCertificate PowerShell 或 az sql mi endpoint-cert show Azure CLI 命令将其导入到 SQL Server,如以下 PowerShell 示例。

注意

使用Azure CLI时,在后续步骤中使用它时,需要手动将 0x 添加到 PublicKey 输出的前面。 例如,PublicKey 将类似于“0x3082033E30...”。

运行以下脚本。 替换:

  • <SubscriptionID> 替换为你的 Azure 订阅 ID。
  • <ManagedInstanceName> 替换为你的托管实例的短名称。
# Run in Azure Cloud Shell (select PowerShell console)
# ===============================================================================
# POWERSHELL SCRIPT TO EXPORT MANAGED INSTANCE PUBLIC CERTIFICATE
# ===== Enter user variables here ====

# Enter your managed instance short name – for example, "sqlmi"
$ManagedInstanceName = "<ManagedInstanceName>"

# ==== Do not customize the following cmdlet ====

# Find out the resource group name
$ResourceGroup = (Get-AzSqlInstance -InstanceName $ManagedInstanceName).ResourceGroupName

# Fetch the public key of the authentication certificate from Managed Instance. Outputs a binary key in the property PublicKey.
Get-AzSqlInstanceEndpointCertificate -ResourceGroupName $ResourceGroup -InstanceName $ManagedInstanceName -EndpointType "DATABASE_MIRRORING" | out-string   

复制整个 PublicKey 输出(以 0x 开头),下一步将需要它。

或者,如果在复制粘贴 PublicKey 时遇到问题,还可以在托管实例上运行 T-SQL 命令 EXEC sp_get_endpoint_certificate 4 以获取其用于链接终结点的公钥。

接下来,将托管实例安全证书的获取公钥导入SQL Server。 对SQL Server运行以下查询以创建 MI 终结点证书。 替换:

  • <ManagedInstanceFQDN> 替换为托管实例的完全限定的域名。
  • <PublicKey> 具有 PublicKey 值,该值是在上一步中从 Azure Cloud Shell 获取的,且以 0x 开头。 无需使用引号。

重要

证书的名称必须是SQL 托管实例 FQDN,不应修改。 如果使用自定义名称,则链接将不起作用。

-- Run on SQL Server
USE MASTER
CREATE CERTIFICATE [<ManagedInstanceFQDN>]
FROM BINARY = <PublicKey> 

将受信任的根证书颁发机构密钥导入到 Azure SQL Server

SQL Server需要将Azure受信任的根证书颁发机构(CA)密钥导入SQL Server,以便信任Azure颁发的SQL 托管实例公钥证书。

可以从 Azure 证书颁发机构详细信息下载必要的根 CA 密钥。 至少下载 DigiCert 全局根 G2Microsoft RSA 根证书颁发机构 2017 证书并将其导入到SQL Server实例。 但是,如果计划运行链接的时间超过几个月,请下载并导入根证书颁发机构节中列出的所有 7 个证书,以防 Azure 更新其受信任的 CA 列表时发生潜在中断。

注意

SQL 托管实例公钥证书的认证路径中的根证书由Azure受信任的根证书颁发机构(CA)颁发。 随着Azure更新其受信任的 CA 列表,特定的根 CA 可能会随时间而变化。 对于简化的设置,请安装 Azure 根证书颁发机构中列出的所有根 CA 证书。 可以通过识别之前导入的 SQL 托管实例 公钥的颁发者来安装所需的 CA 密钥。

将证书保存到SQL Server实例本地,例如示例 C:\Path\To\<name of certificate>.crt 路径,然后使用以下Transact-SQL脚本从该路径导入证书。 将 <name of certificate> 替换为实际的证书名称,例如 DigiCert Global Root G2Microsoft RSA Root Certificate Authority 2017

-- Run on SQL Server
-- Import <name of certificate> root-authority certificate (trusted by Azure), if not already present
IF NOT EXISTS (SELECT name FROM sys.certificates WHERE name = N'<name of certificate>')
BEGIN
    PRINT 'Creating <name of certificate> certificate.'
    CREATE CERTIFICATE [<name of certificate>] FROM FILE = 'C:\Path\To\<name of certificate>.crt'

    --Trust certificates issued by <name of certificate> root authority for Azure database.windows.net domains
    DECLARE @CERTID int
    SELECT @CERTID = CERT_ID('<name of certificate>')
    --For government cloud, use the corresponding SQL Database DNS suffix, e.g. '*.database.usgovcloudapi.net', '*.database.chinacloudapi.cn' etc.
    EXEC sp_certificate_add_issuer @CERTID, N'*.database.windows.net'
END
ELSE
    PRINT 'Certificate <name of certificate> already exists.'
GO

注意

SQL Server 环境中缺少的 sp_certificate_add_issuer 存储过程表明 SQL Server 实例未安装适当的 服务更新

最后,使用以下动态管理视图验证所有创建的证书(DMV):

-- Run on SQL Server
USE master
SELECT * FROM sys.certificates

验证证书链

对证书的计划或意外更改可能会影响链接性能。 为了避免中断,务必在 SQL Server 上定期验证证书链

如果要配置新链接或最近导入证书,请跳过此步骤,如前面的部分所述。

保护数据库镜像终结点

如果没有现有可用性组或SQL Server上的数据库镜像终结点,下一步是在SQL Server上创建数据库镜像终结点,并使用先前生成的SQL Server证书保护该终结点。 如果确实有现有的可用性组或镜像终结点,请跳转到更改现有终结点部分。

在 SQL Server 上创建和保护数据库镜像终结点

要验证您是否尚未创建现有数据库镜像终结点,请使用以下脚本:

-- Run on SQL Server
-- View database mirroring endpoints on SQL Server
SELECT * FROM sys.database_mirroring_endpoints WHERE type_desc = 'DATABASE_MIRRORING'

如果前面的查询未显示现有的数据库镜像终结点,请在SQL Server上运行以下脚本,以获取先前生成的SQL Server证书的名称。

-- Run on SQL Server
-- Show the name and the public key of generated SQL Server certificate
USE MASTER
GO
DECLARE @sqlserver_certificate_name NVARCHAR(MAX) = N'Cert_' + @@servername  + N'_endpoint'
SELECT @sqlserver_certificate_name as 'SQLServerCertName'

从输出中保存 SQLServerCertName,下一步中将需要它。

使用以下脚本在端口 <EndpointPort> 上创建新的数据库镜像终结点,并使用SQL Server证书保护终结点。 替换:

  • <SQL_SERVER_CERTIFICATE> 替换为上一步中获取的 SQLServerCertName 的名称。
-- Run on SQL Server
-- Create a connection endpoint listener on SQL Server
USE MASTER
CREATE ENDPOINT database_mirroring_endpoint
    STATE=STARTED   
    AS TCP (LISTENER_PORT=<EndpointPort>, LISTENER_IP = ALL)
    FOR DATABASE_MIRRORING (
        ROLE=ALL,
        AUTHENTICATION = CERTIFICATE [<SQL_SERVER_CERTIFICATE>],
        ENCRYPTION = REQUIRED ALGORITHM AES
    )  
GO

通过在SQL Server上运行以下脚本来验证镜像终结点是否已创建:

-- Run on SQL Server
-- View database mirroring endpoints on SQL Server
SELECT
    name, type_desc, state_desc, role_desc,
    connection_auth_desc, is_encryption_enabled, encryption_algorithm_desc
FROM 
    sys.database_mirroring_endpoints

成功创建的终结点 state_desc 列应显示为 STARTED

新的镜像终结点是通过 CERTIFICATE 身份验证创建的,并且已启用 AES 加密。

更改现有终结点

注意

如果刚创建了一个新的镜像终结点,请跳过此步骤。 仅当使用现有的可用性组和现有的数据库镜像终结点时,才使用此步骤。

如果将现有可用性组用于链接,或者存在现有的数据库镜像终结点,请先验证它是否满足链接的以下必要条件:

  • 类型必须为 DATABASE_MIRRORING
  • 连接身份验证必须为 CERTIFICATE
  • 必须启用加密。
  • 加密算法必须是 AES

对SQL Server运行以下查询以查看现有数据库镜像终结点的详细信息:

-- Run on SQL Server
-- View database mirroring endpoints on SQL Server
SELECT
    name, type_desc, state_desc, role_desc, connection_auth_desc,
    is_encryption_enabled, encryption_algorithm_desc
FROM
    sys.database_mirroring_endpoints

如果输出显示现有 DATABASE_MIRRORING 终结点的 connection_auth_desc 不是 CERTIFICATE,或者 encryption_algorithm_desc 不是 AES,则需要更改终结点以满足要求。

在SQL Server,同一数据库镜像终结点同时用于可用性组和分布式可用性组。 如果 connection_auth_desc 终结点是 NTLM(Windows 身份验证)或 KERBEROS,并且您需要现有可用性组使用 Windows 身份验证,可以通过将身份验证选项切换到 NEGOTIATE CERTIFICATE,从而更改终结点以使用多种身份验证方法。 此更改允许现有可用性组使用Windows 身份验证,同时对SQL 托管实例使用证书身份验证。

同样,如果加密不包含 AES 并且你需要 RC4 加密,也有可能可以将终结点更改为使用这两种算法。 有关更改终结点选项的详细信息,请参阅 sys.database_mirroring_endpoints 的文档页面。

以下脚本是有关如何在 SQL Server 上更改现有数据库镜像终结点的示例。 替换:

  • <YourExistingEndpointName> 使用现有的终结点名称。
  • <SQLServerCertName>,其名称为生成的SQL Server证书(在上述步骤之一中获取)。

根据你的特定配置,可能需要进一步自定义脚本。 还可以使用 SELECT * FROM sys.certificates 获取在 SQL Server 上创建的证书的名称。

-- Run on SQL Server
-- Alter the existing database mirroring endpoint to use CERTIFICATE for authentication and AES for encryption
USE MASTER
ALTER ENDPOINT [<YourExistingEndpointName>]   
    STATE=STARTED   
    AS TCP (LISTENER_PORT=<EndpointPort>, LISTENER_IP = ALL)
    FOR DATABASE_MIRRORING (
        ROLE=ALL,
        AUTHENTICATION = WINDOWS NEGOTIATE CERTIFICATE [<SQLServerCertName>],
        ENCRYPTION = REQUIRED ALGORITHM AES
    )
GO

运行 ALTER 终结点查询并将双重身份验证模式设置为Windows和证书后,请在SQL Server再次使用此查询来显示数据库镜像终结点的详细信息:

-- Run on SQL Server
-- View database mirroring endpoints on SQL Server
SELECT
    name, type_desc, state_desc, role_desc, connection_auth_desc,
    is_encryption_enabled, encryption_algorithm_desc
FROM
    sys.database_mirroring_endpoints

已成功修改用于SQL 托管实例链接的数据库镜像终结点。

在 SQL Server 上创建可用性组

如果没有现有的可用性组,下一步是在SQL Server上创建一个可用性组,而不管哪个是初始主数据库。

注意

如果已有可用性组,请跳过此部分。

如果SQL 托管实例是初始主数据库,则创建可用性组的命令不同,仅支持从 SQL Server 2022 CU10 开始。

虽然可以为同一数据库建立多个链接,但该链接仅支持每个链接复制一个数据库。 如果要为同一数据库创建多个链接,请对所有链接使用相同的可用性组,但随后为SQL Server和SQL 托管实例之间的每个数据库链接创建新的分布式可用性组。

如果SQL Server是初始主数据库,请创建具有以下链接参数的可用性组:

  • 初始主服务器名称
  • 数据库名称
  • 故障转移模式 MANUAL
  • 种子模式 AUTOMATIC

首先,通过运行以下 T-SQL 语句找出SQL Server名称:

-- Run on the initial primary
SELECT @@SERVERNAME AS SQLServerName 

然后,使用以下脚本在SQL Server上创建可用性组。 替换:

  • 在 SQL Server 上使用您的可用性组名称替换 <AGNameOnSQLServer>。 托管实例链接要求每个可用性组拥有一个数据库。 对于多个数据库,需要创建多个可用性组。 请考虑命名每个可用性组,使其名称反映相应的数据库 - 例如 AG_<db_name>
  • <DatabaseName> 替换为要复制的数据库的名称。
  • <SQLServerName>,其中包含在上一步中获取的SQL Server实例的名称。
  • 具有SQL Server IP 地址的 <SQLServerIP>。 可以使用可解析SQL Server主机名称作为替代方法,但需要确保该名称可从SQL 托管实例虚拟网络解析。
-- Run on SQL Server
-- Create the primary availability group on SQL Server
USE MASTER
CREATE AVAILABILITY GROUP [<AGNameOnSQLServer>]
WITH (CLUSTER_TYPE = NONE) -- <- Delete this line for SQL Server 2016 only. Leave as-is for all higher versions.
    FOR database [<DatabaseName>]  
    REPLICA ON   
        N'<SQLServerName>' WITH   
            (  
            ENDPOINT_URL = 'TCP://<SQLServerIP>:<EndpointPort>',
            AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,
            FAILOVER_MODE = MANUAL,
            SEEDING_MODE = AUTOMATIC
            );
GO

重要

对于 SQL Server 2016,请从上述 T-SQL 语句中删除 WITH (CLUSTER_TYPE = NONE)。 保留所有后续 SQL Server 版本的配置不变。

接下来,在SQL Server上创建分布式可用性组。 如果计划创建多个链接,则需要为每个链接创建分布式可用性组,即使要为同一数据库建立多个链接也是如此。

替换以下值,然后运行 T-SQL 脚本来创建分布式可用性组。

  • <DAGName> 使用分布式可用性组的名称。 由于可以通过为每个链接创建分布式可用性组来为同一数据库配置多个链接,因此请考虑相应地命名每个分布式可用性组,例如 DAG1_<db_name>DAG2_<db_name>
  • <AGNameOnSQLServer> 替换为上一步中创建的可用性组的名称。
  • <AGNameOnSQLMI> 在 SQL 托管实例中的可用性组名称。 该名称在 SQL MI 上必须是唯一的。 请考虑命名每个可用性组,使其名称反映相应的数据库 - 例如 AG_<db_name>_MI
  • <SQLServerIP>替换为上一步中 SQL Server 的 IP 地址。 可以使用可解析SQL Server主机名称作为替代方法,但请确保该名称可从SQL 托管实例虚拟网络解析(这需要为托管实例的子网配置自定义Azure DNS)。
  • <ManagedInstanceName> 替换为你的托管实例的短名称。
  • <ManagedInstanceFQDN> 替换为托管实例的完全限定域名。
-- Run on SQL Server
-- Create a distributed availability group for the availability group and database
-- ManagedInstanceName example: 'sqlmi1'
-- ManagedInstanceFQDN example: 'sqlmi1.73d19f36a420a.database.windows.net'
USE MASTER
CREATE AVAILABILITY GROUP [<DAGName>]
WITH (DISTRIBUTED) 
    AVAILABILITY GROUP ON  
    N'<AGNameOnSQLServer>' WITH 
    (
      LISTENER_URL = 'TCP://<SQLServerIP>:<EndpointPort>',
      AVAILABILITY_MODE = ASYNCHRONOUS_COMMIT,
      FAILOVER_MODE = MANUAL,
      SEEDING_MODE = AUTOMATIC,
      SESSION_TIMEOUT = 20
    ),
    N'<AGNameOnSQLMI>' WITH
    (
      LISTENER_URL = 'tcp://<ManagedInstanceFQDN>:5022;Server=[<ManagedInstanceName>]',
      AVAILABILITY_MODE = ASYNCHRONOUS_COMMIT,
      FAILOVER_MODE = MANUAL,
      SEEDING_MODE = AUTOMATIC
    );
GO

验证可用性组

使用以下脚本列出SQL Server实例上的所有可用性组和分布式可用性组。 此时,可用性组状态需要是 connected,并且分布式可用性组状态需要是 disconnected。 分布式可用性组的状态仅当加入SQL 托管实例时会变为connected

-- Run on SQL Server
-- This will show that the availability group and distributed availability group have been created on SQL Server.
SELECT * FROM sys.availability_groups

或者,可以使用 SSMS 对象资源管理器查找可用性组和分布式可用性组。 展开“Always On 高可用性”文件夹,然后展开“可用性组”文件夹。

最后,可以创建链接。 根据哪个实例为初始主要副本,这些命令会有所不同。 使用 New-AzSqlInstanceLink PowerShell 或 az sql mi link create Azure CLI 命令创建链接,如本节中的 PowerShell 示例。 Azure CLI目前不支持从SQL 托管实例主节点建立连接。

如果需要查看托管实例上的所有链接,请使用 Azure Cloud Shell 中的 Get-AzSqlInstanceLink PowerShell 或 az sql mi 链接 show Azure CLI 命令。

若要简化此过程,请登录到 Azure 门户,并从Azure Cloud Shell运行以下脚本。 替换:

  • <ManagedInstanceName> 替换为你的托管实例的短名称。
  • <AGNameOnSQLServer>,其中包含在SQL Server上创建的可用性组的名称。
  • <AGNameOnSQLMI>,其中包含在SQL 托管实例上创建的可用性组的名称。
  • <DAGName>,其中包含在SQL Server上创建的分布式可用性组的名称。
  • <DatabaseName>,SQL Server上可用性组中复制的数据库。
  • <SQLServerIP> 使用 SQL Server 的 IP 地址。 托管实例必须可以访问提供的 IP 地址。

注意

如果要建立指向已存在的可用性组的链接,请在提供 <SQLServerIP> 参数时提供侦听器的 IP 地址。 请确保已在所有可用性组节点与SQL 托管实例之间建立信任(请参阅实例之间的信任关系部分)。

#  Run in Azure Cloud Shell (select PowerShell console)
# =============================================================================
# POWERSHELL SCRIPT TO CREATE MANAGED INSTANCE LINK
# Instructs Managed Instance to join distributed availability group on SQL Server
# ===== Enter user variables here ====

# Enter your managed instance name – for example, "sqlmi1"
$ManagedInstanceName = "<ManagedInstanceName>"

# Enter the availability group name that was created on SQL Server
$AGNameOnSQLServer = "<AGNameOnSQLServer>"

# Enter the availability group name that was created on SQL Managed Instance
$AGNameOnSQLMI = "<AGNameOnSQLMI>"

# Enter the distributed availability group name that was created on SQL Server
$DAGName = "<DAGName>"

# Enter the database name that was placed in the availability group for replication
$DatabaseName = "<DatabaseName>"

# Enter the SQL Server IP
$SQLServerIP = "<SQLServerIP>"

# ==== Do not customize the following cmdlet ====

# Find out the resource group name
$ResourceGroup = (Get-AzSqlInstance -InstanceName $ManagedInstanceName).ResourceGroupName

# Build properly formatted connection endpoint
$SourceIP = "TCP://" + $SQLServerIP + ":<EndpointPort>"

# Create link on managed instance. Join distributed availability group on SQL Server.
New-AzSqlInstanceLink -ResourceGroupName $ResourceGroup -InstanceName $ManagedInstanceName -Name $DAGName |
-PartnerAvailabilityGroupName $AGNameOnSQLServer -InstanceAvailabilityGroupName $AGNameOnSQLMI |
-Database @($DatabaseName) -PartnerEndpoint $SourceIP -InstanceLinkRole Secondary

此操作的结果会是成功执行创建链接请求时的时间戳。

若要验证SQL 托管实例与SQL Server之间的连接,请在SQL Server上运行以下查询。 连接不会是即时的。 最多可能需要一分钟的时间,DMV 才会开始显示成功的连接。 继续刷新 DMV,直到连接显示为已连接的 SQL 托管实例副本。

-- Run on SQL Server
SELECT
    r.replica_server_name AS [Replica],
    r.endpoint_url AS [Endpoint],
    rs.connected_state_desc AS [Connected state],
    rs.last_connect_error_description AS [Last connection error],
    rs.last_connect_error_number AS [Last connection error No],
    rs.last_connect_error_timestamp AS [Last error timestamp]
FROM
    sys.dm_hadr_availability_replica_states rs
    JOIN sys.availability_replicas r
    ON rs.replica_id = r.replica_id

建立连接后,SSMS 中的对象资源管理器可能会在辅助副本上的复制数据库最初显示为还原状态,因为在初始种子阶段,会移动并还原数据库的完整备份。 数据库还原后,复制必须跟上,使两个数据库保持同步状态。 初始填充完成后,该数据库将不再处于“正在还原”状态。 如果小型数据库的初始化速度足够快,您可能在 SSMS 中看不到初始的“正在还原”状态。

重要

  • 除非SQL Server与SQL 托管实例之间存在网络连接,否则该链接将不起作用。 若要解决网络连接问题,请按照测试网络连接中的步骤操作。
  • 在SQL Server定期备份日志文件。 如果已用日志空间达到 100%,则复制到SQL 托管实例停止,直到空间使用减少。 强烈建议通过设置每日作业来自动执行日志备份。 有关详细信息,请参阅 在 SQL Server 上备份日志文件。

进行第一次事务日志备份

如果 SQL Server 是您的初始主数据库,请务必在初始种子设定完成后,当数据库在 Azure SQL 托管实例上不再处于 Restoring... 状态时,在 SQL Server 上执行第一个事务日志备份。 然后定期执行 SQL Server 事务日志备份,以最大程度地减少过多的日志增长,同时 SQL Server 处于主服务器角色。

如果 SQL 托管实例是主实例,则您无需执行任何操作,因为 Azure SQL 托管实例会自动执行日志备份。

如果想删除链接,无论是因为不再需要它,还是因为它处于无法修复的状态并需要重新创建,则都可以使用 PowerShell 和 T-SQL 来执行此操作。

首先,使用 Remove-AzSqlInstanceLink PowerShell 命令删除链接,如以下示例:

Remove-AzSqlInstanceLink -ResourceGroupName $ResourceGroup -InstanceName $managedInstanceName -Name $DAGName -Force 

然后,在SQL Server上运行以下 T-SQL 脚本来删除分布式可用性组。 将 <DAGName> 替换为用于创建链接的分布式可用性组的名称:

USE MASTER 
GO 

DROP AVAILABILITY GROUP <DAGName>  
GO 

最后,如果不再需要可用性组,则可以选择将其删除。 为此,请将 <AGName> 替换为可用性组的名称,然后在相应的实例上运行它:

DROP AVAILABILITY GROUP <AGName>  
GO 

故障排除

如果在创建链接时遇到错误消息,请查看查询输出窗口中的错误消息以了解详细信息。 有关详细信息,请参阅排查链接问题

要使用该链接,请参阅以下内容:

要了解有关该链接的详细信息,请参阅以下内容:

对于其他复制和迁移方案,请考虑: