【问题标题】:replication between two tables with different names and which have different column names. Is it possible to create such replication在具有不同名称和不同列名的两个表之间进行复制。是否可以创建这样的复制
【发布时间】:2011-08-07 16:30:48
【问题描述】:

我有一个要求,我在两个具有不同名称和不同列名的表之间创建复制。是否可以创建这样的复制。

server A                                            server B
----------                                          ----------
Table : Test                                        Table : SUBS
--------------                                      ---------------
columns A,B,C                                       Columns D,E,F,G,H

我想配置复制,以便将 A 列数据复制到 D 列,将 B 列数据复制到 E 列,将 C 列数据复制到 F 列

【问题讨论】:

标签: sql-server sql-server-2008 replication database-replication merge-replication


【解决方案1】:

显然,答案是:“定义文章时,您必须将 @vertical_partition 参数设置为 true,然后使用 sp_articlecolumn 添加所需的列。”

但是,我不得不问你为什么要这样做。在我看来,复制并不是用于在不同数据库之间移动数据的通用工具,而是用于保持两个相同数据库同步的工具。

其他集思广益的想法:

  • 您可以创建一个与目标表匹配的新源表,并使用触发器保持源表同步。
  • 将源表原封不动地推送到目标并在目标数据库中执行 MERGE。
  • 在这里,复制可能不是真正的解决方案。要求执行此操作的业务规则和要求是什么?您是否考虑过使用 SSIS?
  • 如果需要两个表始终精确同步,那么源表的更改通道是什么——一个应用程序?听起来您的应用程序几乎需要一个新的抽象级别,即知道如何同时写入两个源的数据写入层。

试图在两个不同的数据库之间保持数据同步可能是个问题。竞态条件、缺乏分布式事务(影响一致性和对故障的响应)、为处理没有分布式事务而创建的变通方法存在问题等等,都可能存在各种微妙的问题。您能否改为创建一个链接服务器和一些视图,这些视图实际上使一个数据库中的数据可以从另一个数据库中实时访问?

请告诉我们更多关于您的要求以及为什么需要这样做。

更新

如果您采用手动更新路线,请注意您不能同时应用时间段的插入、更新和删除操作。您必须一次应用一个,按顺序。如果您改为使用 当前状态 而不是中间数据操作,那么您可以一次执行所有行。我将向您展示 MERGE 示例,而不是历史回放示例。

BEGIN TRAN;

DELETE D
FROM LinkedServer.dbo.Dest D WITH (TABLOCKX, HOLDLOCK)
WHERE
   NOT EXISTS (
      SELECT *
      FROM Source S
      WHERE D.Key = S.Key
   );

UPDATE D
SET
   D.Col1 = S.Col4,
   D.Col2 = S.Col5,
   D.Col3 = S.Col6,
   D.Col4 = S.Col7,
FROM
   LinkedServer.dbo.Dest D
   INNER JOIN Source S ON D.Key = S.Key
WHERE
   D.Col1 <> S.Col4
   OR EXISTS (
      SELECT D.Col2, D.Col4
      EXCEPT
      SELECT S.Col3, S.Col6
   ); -- or some other way to handle comparison of nullable columns

INSERT LinkedServer.dbo.Dest (Col1, Col2, Col3)
SELECT Col4, Col5, Col6
FROM Source S WITH (TABLOCK, HOLDLOCK)
WHERE
   NOT EXISTS (
      SELECT *
      FROM LinkedServer.dbo.Dest D
      WHERE S.Key = D.Key
   );

COMMIT TRAN;

您可能会发现推送整个表并在目标服务器上执行合并操作会更好。

如果您要获得一致的时间点快照,我在第一个查询中添加的锁定提示很重要。如果您不关心这一点,请取消锁定提示。

如果您发现跨链接服务器的更新速度很慢,则将整个表一起推送到远程服务器上的临时临时表,并完全在远程服务器上的脚本中执行 MERGE。

【讨论】:

  • 我只是想更新两个不同位置的两个数据库。正如你所说,我创建了一个临时表并使用触发器在临时表中插入了任何更新或插入的记录。然后使用存储过程和计划作业和链接服务器在远程数据库中插入或更新等效记录。但我的问题是关于分布式事务。我在连接松散期间的问题会满足使用分布式事务吗?假设在更新远程数据库期间连接松动。使用分布式事务够吗?
  • 你需要查找分布式事务。开始一个 tran,在链接服务器上进行更新,删除本地行,然后提交。如果这行得通,你就是金子。如果它抱怨分布式事务,那么你还有一些工作要做。
  • 我搜索了分布式事务,但我不知道应该使用Rollback 语句还是使用commit 来满足分布式事务?可以举个例子吗?
  • 感谢@Erik 的回答。我写了一个包含三个步骤的作业,并安排了每 5 分钟重复一次的作业。第一步插入,第二步更新,第三步删除。我做得对吗?第一步完成后,第二步将运行,如果第一步成功完成,第二步将运行,第三步也是如此。
  • @Raymond,不,您需要将三个语句放在一个事务中。单独执行它们是没有意义的,因为那样你的远程表将不代表一个时间点。虽然这可能不是很严重,但没有理由不将所有更新放在一个脚本中。另外,如果我上面的查询对您有用,那么您就知道分布式事务正在工作并且 DTC 服务正在两个服务器上运行,并且权限设置为正确允许它们。
猜你喜欢
  • 2011-07-19
  • 2018-04-03
  • 2019-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-27
相关资源
最近更新 更多