有没有办法使用可用性组功能在 SQL Server 2012 上实现跨数据库任务?

met*_*avl 6 sql-server-2012 availability-groups distributed-transactions

我们使用 SQL Server 2012 及其新的可用性组 (AG) 功能。有一项任务是将某些表的旧数据从一个数据库移动到另一个数据库。两个数据库都包含在不同的可用性组中。

以前(在使用 AG 功能之前)通过将第二个服务器实例添加为链接服务器 ( sp_addlinkedserver) 并按以下方式执行分布式事务来解决该任务:

  1. 开始交易
  2. 将旧数据从 server1.table1 插入 server2.table2
  3. 从 server1.table1 中删除旧数据
  4. 提交事务

不幸的是,AG 不支持分布式事务,因为在故障转移的情况下数据库可能会变得不一致 ( http://technet.microsoft.com/en-us/library/ms366279.aspx )。

是否有某种方法可以在保留 AG 功能的情况下实现此任务,并且在发生异常时不实现回滚逻辑?

Bre*_*zar 1

首先,从技术上讲,您可以使用 DTC 或链接服务器事务来完成此操作 - 只是不支持它,并且无论如何这对于性能来说都是一个坏主意。我们来谈谈更好的方法。

问题的编写方式听起来像是您正在进行归档 - 将数据从 Server1.Table1 上的“当前”表移动到 Server2.Table2 上的一组“归档”表。在这种情况下,如果数据在两个地方都存在很短的时间也没关系,所以我会将其分成两个单独的任务:

第 1 阶段:复制- 将旧数据从 server1.table1 插入到 server2.table2 中。假设这是一个归档过程,您可以将其作为计划作业,在每晚午夜运行(或任何适合您的日期/时间)。

第 2 阶段:删除- 从 server2.table2 的只读副本中读取,删除 server1.table1 中仍然存在的数据。将其作为计划作业执行,该作业在第 1 阶段后运行 X 分钟,每 X 分钟运行一个小时(或者无论您想重试多少次)。这样,如果只读副本在几分钟后运行,您的删除仍将最终发生。

从只读副本而不是直接从 server2 读取非常重要 - 毕竟,您的目标是确保数据真正受到保护。(这就是不支持跨数据库的原因。)

为了提高性能而设计,我实际上也不会在 server2.table2 和 server1.table1 之间加入 - 这会导致阻塞混乱。相反,获取 server2.table2 中的最大 ID,这将告诉您要在 server1 上删除的数据。如果 ID# 500 的记录已到达 server2.table2,那么您可以删除 server1.table1 上所有 ID <= 500 的记录。您可以对日期使用相同的技巧。如果您使用快速有序删除技术,则会获得奖励积分。

如果您要归档单个记录而不是通过 ID 或日期字段,您仍然需要在表之间直接联接 - 只是不要直接在 server2 上联接,而是在其只读副本上联接。

是的,这比事务中包含的单个删除语句需要更多工作,但是当您开始突破性能和可用性边界(例如使用 AlwaysOn AG 跨多个服务器扩展数据)时,您必须自己做更多这些事情,而不是点击简单按钮,呵呵。