使用 Azure SQL 托管实例进行事务性复制

适用于:Azure SQL 托管实例

事务复制是 Azure SQL 托管实例和 SQL Server 的一项功能,用于将 Azure SQL 托管实例或 SQL Server 实例中表的数据复制到远程数据库中的表。 使用此功能可以同步不同数据库中的多个表。

概述

还可以使用事务复制将 Azure SQL 托管实例中发生的更改推送到:

  • SQL Server 数据库(本地或 Azure 虚拟机)
  • Azure SQL 数据库中的数据库
  • Azure SQL 托管实例中的实例数据库

注意

若要使用 Azure SQL 托管实例的所有功能,必须使用最新版本的 SQL Server Management Studio (SSMS)SQL Server Data Tools (SSDT)

组件

事务复制的关键组件是“发布服务器”、“分发服务器”和“订阅服务器”,如下图所示 :

使用 Azure SQL 进行复制的关系图。

角色 Azure SQL 数据库 Azure SQL 托管实例
发布者
分发服务器
提取订阅服务器
推送订阅服务器

“发布服务器”通过将更新发送到分发服务器,来发布某些表(项目)所发生的更改。 发布服务器可以是 Azure SQL 托管实例或 SQL Server 实例。

“分发服务器”从发布服务器收集项目中的更改,并将其分发到订阅服务器。 分发服务器可以是 Azure SQL 托管实例或 SQL Server 实例(可以采用等于或高于发布服务器版本的任何版本)。

“订阅服务器”接收在发布服务器上发生的更改。 SQL Server 实例和 Azure SQL 托管实例都可以是推送和请求订阅服务器,但当分发服务器是 Azure SQL 托管实例而订阅服务器不是时,则请求订阅不受支持。 Azure SQL 数据库中的数据库只能是推送订阅服务器。

Azure SQL 托管实例可以支持成为以下版本的 SQL Server 的订阅服务器:

注意

对于不支持发布到 Azure 中的对象的其他 SQL Server 版本,可以使用重新发布数据方法将数据移动到较新版本的 SQL Server。

尝试使用旧版来配置复制可能导致错误 MSSQL_REPL20084(过程无法连接到订阅服务器)和 MSSQL_REPL40532(无法打开登录名所请求的服务器 <名称>。登录失败)。

复制类型

有不同的复制类型

复制 Azure SQL 数据库 Azure SQL 托管实例
标准事务 是(仅用作订阅服务器)
快照 是(仅用作订阅服务器)
合并复制
对等
双向
可更新订阅

可支持性矩阵

Azure SQL 托管实例的事务复制可支持性矩阵与 SQL Server 的相同。

发布者 分发服务器 订阅服务器
SQL Server 2022 SQL Server 2022 SQL Server 2022
SQL Server 2019
SQL Server 2017
SQL Server 2019 SQL Server 2022
SQL Server 2019
SQL Server 2022
SQL Server 2019
SQL Server 2017
SQL Server 2016
SQL Server 2017 SQL Server 2022
SQL Server 2019
SQL Server 2017
SQL Server 2022
SQL Server 2019
SQL Server 2017
SQL Server 2016
SQL Server 2014
SQL Server 2016 SQL Server 2022
SQL Server 2019
SQL Server 2017
SQL Server 2016
SQL Server 2019
SQL Server 2017
SQL Server 2016
SQL Server 2014
SQL Server 2012
SQL Server 2014 SQL Server 2022
SQL Server 2019
SQL Server 2017
SQL Server 2016
SQL Server 2014
SQL Server 2017
SQL Server 2016
SQL Server 2014
SQL Server 2012
SQL Server 2008 R2
SQL Server 2008
SQL Server 2012 SQL Server 2022
SQL Server 2019
SQL Server 2017
SQL Server 2016
SQL Server 2014
SQL Server 2012
SQL Server 2016
SQL Server 2014
SQL Server 2012
SQL Server 2008 R2
SQL Server 2008
SQL Server 2008 R2
SQL Server 2008
SQL Server 2022
SQL Server 2019
SQL Server 2017
SQL Server 2016
SQL Server 2014
SQL Server 2012
SQL Server 2008 R2
SQL Server 2008
SQL Server 2014
SQL Server 2012
SQL Server 2008 R2
SQL Server 2008

何时使用

在以下情况下,事务复制非常有用:

  • 发布数据库的一个或多个表中所做的更改,并将其分发到订阅了更改的 SQL Server 实例或 Azure SQL 数据库中的一个或多个数据库。
  • 将多个分布式数据库保持同步状态。
  • 通过持续发布更改,将数据库从一个 SQL Server 实例或 Azure SQL 托管实例迁移到另一个数据库。

将数据同步与事务复制进行比较

类别 数据同步 事务复制
优点 - 主动-主动支持
- 在本地和 Azure SQL 数据库之间双向同步
- 更低的延迟
- 事务一致性
- 迁移后重用现有拓扑
缺点 - 无事务一致性
- 更高的性能影响
- 无法从 Azure SQL 数据库发布
- 维护成本高

常用配置

一般情况下,发布服务器和分发服务器必须都在云中,或者都在本地。 支持以下配置:

带本地分发服务器的发布服务器位于 SQL 托管实例上

用作发布服务器和分发服务器的单个实例。

发布服务器和分发服务器在单个 SQL 托管实例中配置,并将更改分发到其他 SQL 托管实例、SQL 数据库或 SQL Server 实例。

带远程分发服务器的发布服务器位于 SQL 托管实例上

在此配置中,由一个 SQL 托管实例将更改发布到能够为许多源 SQL 托管实例提供服务的另一个 SQL 托管实例上的分发服务器,并将更改分发到 Azure SQL 数据库、Azure SQL 托管实例或 SQL Server 上的一个或多个目标。

发布服务器和分发服务器的独立实例。

在两个托管实例上配置发布服务器和分发服务器。 此配置存在一些约束:

  • 两个托管实例位于同一 vNet 中。
  • 两个托管实例都位于同一位置。

本地发布服务器/分发服务器与远程订阅服务器

Azure SQL 数据库作为订阅服务器。

在此配置中,Azure SQL 数据库或 Azure SQL 托管实例中的数据库是订阅服务器。 此配置支持从本地迁移到 Azure。 如果订阅服务器是 Azure SQL 数据库中的数据库,则它必须处于推送模式。

要求

  • 使用 SQL 身份验证实现复制参与者之间的连接。
  • 对复制功能使用的工作目录使用 Azure 存储帐户共享。
  • 在子网安全规则中打开 TCP 出站端口 445 以访问 Azure 文件共享。
  • 当 SQL 托管实例是发布服务器/分发服务器,而订阅服务器不是时,请打开 TCP 出站端口 1433。 对于端口 1433 目标服务标记,你可能还需要将 allow_linkedserver_outbound 的 SQL 托管实例 NSG 出站安全规则从 virtualnetwork 更改为 internet
  • 将发布服务器和分发服务器都置于云中,或都置于本地。
  • 如果虚拟网络不同,请配置复制参与者的虚拟网络之间的 VPN 对等互连。

注意

当分发服务器为 Azure SQL 托管实例数据库且订阅服务器位于本地时,如果阻止出站网络安全组 (NSG) 端口 445,则会在连接到 Azure 存储文件时遇到错误 53。 更新 vNet NSG 以解决此问题。

限制

事务复制有一些特定于 Azure SQL 托管实例的限制。 在本部分中详细了解这些限制。

不会从 Azure 存储帐户中删除快照文件

Azure SQL 托管实例正在为用于事务复制的快照文件使用用户配置的 Azure 存储帐户。 与本地环境中的 SQL Server 不同,Azure SQL 托管实例不会从 Azure 存储帐户中删除快照文件。 不再需要文件后,应将其删除。 这可以通过 Azure 门户上的 Azure 存储接口、Microsoft Azure 存储资源管理器或通过命令行客户端(Azure PowerShell 或 CLI)或者 Azure 存储管理 REST API 来完成。

下面是如何删除文件以及如何删除空文件夹的示例。

az storage file delete-batch --source <file_path> --account-key <account_key> --account-name <account_name>
az storage directory delete --name <directory_name> --share-name <share_name> --account-key <account_key> --account-name <account_name>

连续运行的分发代理数

配置为连续运行的分发代理的数量在 Azure SQL 托管实例上限制为 30 个。 若要拥有更多分发代理,它们需要按需运行或按定义的计划运行。 计划可以定义为每日频率和每 10 秒(或更长时间)发生一次,因此即使它不是连续的,你仍然可以让分发服务器引入仅几秒的延迟。 当需要大量分发服务器时,建议使用计划配置而不是连续配置。

使用故障转移组

支持对故障转移组中的实例使用事务复制。 但是,如果在将 SQL 托管实例添加到故障转移组之前配置复制,则复制会在你开始创建故障转移组时暂停,并且复制监视器显示状态 Replicated transactions are waiting for the next log backup or for mirroring partner to catch up。 一旦成功创建故障转移组,复制就会恢复。

如果发布服务器分发服务器 SQL 托管实例位于故障转移组中,则 SQL 托管实例管理员必须清理旧的主实例上的所有发布内容,然后在故障转移后,在新的主实例上重新配置这些发布内容。 在此方案中,需要执行以下活动:

  1. 停止数据库上运行的所有复制作业(如果有)。

  2. 通过在发布服务器数据库上运行以下脚本,删除发布服务器中的订阅元数据。 替换 <name of publication><name of subscriber> 值:

    EXEC sp_dropsubscription @publication = '<name of publication>',
        @article = 'all',
        @subscriber = '<name of subscriber>'
    
  3. 删除订阅服务器中的订阅元数据。 对订阅服务器 SQL 托管实例上的订阅数据库运行以下脚本。 替换 <full DNS of publisher> 值。 例如,example.ac2d23028af5.database.chinacloudapi.cn

    EXEC sp_subscription_cleanup
       @publisher = N'<full DNS of publisher>',
       @publisher_db = N'<publisher database>',
       @publication = N'<name of publication>';
    
  4. 通过在已发布的数据库中运行以下脚本,强制删除发布服务器中的所有复制对象:

    EXEC sp_removedbreplication;
    
  5. 强制删除原始主 SQL 托管实例中的旧分发服务器(如果故障回复到曾经具有分发服务器的旧主实例)。 在旧分发服务器 SQL 托管实例中的 master 数据库上运行以下脚本:

    EXEC sp_dropdistributor 1, 1;
    

如果订阅服务器 SQL 托管实例位于故障转移组中,则应将发布配置为连接到订阅服务器 SQL 托管实例的故障转移组侦听器终结点。 发生故障转移时,SQL 托管实例管理员执行的后续操作取决于发生的故障转移类型:

  • 如果在不丢失数据的情况下进行故障转移,则故障转移后复制将继续工作。
  • 如果在丢失数据的情况下进行故障转移,复制也能正常工作。 它会再次复制丢失的更改。
  • 如果在丢失数据的情况下进行故障转移,但数据丢失发生在分发数据库保留期以外,则 SQL 托管实例管理员需要重新初始化订阅数据库。

排查常见问题

事务日志和事务复制

通常,事务日志用于记录数据库内数据的更改。 更改记录在事务日志中,这会使日志存储消耗量增加。 还有一个允许安全截断事务日志的自动流程,该流程可减少日志的已用存储空间。 配置事务复制发布时,将阻止事务日志截断,直到日志读取器作业处理日志中的更改。 在某些情况下,实际上阻止了事务日志的处理,并且该状态可能会导致为事务日志保留的整个存储被填满。 如果没有可用空间用于存储事务日志,并且没有更多空间用于满足事务日志增长需求,则表示我们的事务日志已满。 在此状态下,数据库无法再处理任何写入工作负载,并且实际上成为只读数据库。

禁用的日志读取器代理

有时为数据库配置了事务复制发布,但未对日志读取器代理进行运行配置。 在这种情况下,更改将累积在事务日志中,并且不会处理这些更改。 这会导致事务日志持续增长,并最终增长到已满事务日志。 用户应确保日志读取器作业存在且处于活动状态。 或者,在不需要事务复制时将其禁用。

日志读取器代理查询超时

有时,由于重复的查询超时,日志读取器作业无法有效推进。 修复查询超时的一种方法是提高日志读取器代理作业的查询超时设置。

可以使用 SSMS 增加日志读取器作业的查询超时时间。 在 SQL Server 代理下的对象资源管理器中,找到要修改的作业。 首先停止作业,然后打开其属性。 查找 step 2 并进行编辑。 在命令值后追加 -QueryTimeout <timeout_in_seconds>。 对于查询超时值,可尝试使用 21600 或更大值。 最后,重新启动作业。

日志存储大小达到上限 2 TB

当事务日志存储大小达到上限(即 2 TB)时,日志实际上无法继续增加,超过这一限值。 在这种情况下,唯一可用的缓解措施是将要复制的所有事务标记为“已处理”,以允许截断事务日志。 这实际上意味着不会复制日志中剩余的事务,并且需要重新初始化复制。

注意

执行缓解措施后,需要重新初始化复制,这意味着重新复制整个数据集。 这是要操作的数据大小,可能会运行较长时间,具体取决于要复制的数据量。

若要执行缓解措施,首先需要停止分发服务器上日志读取器代理。 然后,需要在发布服务器数据库运行 sp_repldone 存储过程,并将 reset 标志设置为 1,以允许截断事务日志。 此命令应如下所示 EXEC sp_repldone @xactid = NULL, @xact_seqno = NULL, @numtrans = 0, @time = 0, @reset = 1。 之后,需要重新初始化复制。

后续步骤

有关配置事务复制的详细信息,请参阅以下教程: