SQL Server 多对一复制

Joh*_*mer 14 replication sql-server sql-server-2008-r2

我有 8 台单独的 SQL Server 2008 R2 机器,每台机器托管 1 个数据库。每个数据库都有相同的表结构和模式,以及完全独特的数据。

我想建立一个报告服务器(可能是 2008 年或 2012 年),它将来自 8 个源服务器的选定表中的行合并到报告服务器上这些表的单个实例中。这是单向复制(不会对报告服务器进行任何更改)。我需要以相对较低的延迟(比如 20-30 秒)从源数据库复制更改。

此外,我想找到方法来实现这一点,对源服务器的影响尽可能小。在我的环境中,这些服务器的第 3 方代理、触发器或模式修改很困难。

我的问题:

  • 实现这一目标的有前途的架构和技术是什么?
  • 我看过 SQL Server 合并复制,但我担心延迟。这是实现此目标的合适技术吗?
  • 是否有用于事务复制的多对一架构?
  • 我是否应该在我的报告服务器上查看 8 个数据库中的一对一复制,然后是一些自定义合并功能(两步复制)?

谢谢,约翰

Kin*_*hah 16

我有 8 台单独的 SQL Server 2008 R2 机器,每台机器托管 1 个数据库。每个数据库都有相同的表结构和模式,以及完全独特的数据。我想建立一个报告服务器(可能是 2008 年或 2012 年),它将来自 8 个源服务器的选定表中的行合并到报告服务器上这些表的单个实例中。这是单向复制(不会对报告服务器进行任何更改)。我需要以相对较低的延迟(比如 20-30 秒)从源数据库复制更改。

您可以通过事务复制来实现这一点。以下是您如何做到这一点。

注意:您必须稍微更改您的表架构以实现此目的,因为您必须在复制到订阅者时唯一地标识这些行。作为 T-Rep 的先决条件,您需要有定义了 PK 的表。

以下是发布服务器上的示例表,该表位于要合并报告服务器上的行的所有 8 台服务器上:

CREATE TABLE Products
(
ProductID INT not null,
ProductName VARCHAR(25),
ServerName sysname default @@servername not null -- this is to identify which row is from which server ; probably add this using Alter column
)
GO
ALTER TABLE Products
ADD CONSTRAINT pk_Product_ID_ServerName PRIMARY KEY (ProductID)
Run Code Online (Sandbox Code Playgroud)

订阅服务器上,您需要创建相同的表但使用不同的 PK 来唯一标识订阅者处的行(不这样做,T-Rep 将因 PK 违规而失败 - 我假设您无法修改 PK 结构现场制作而不是在订阅者处进行修改更好)

CREATE TABLE Products
(
ProductID INT not null,
ProductName VARCHAR(25),
ServerName sysname default @@servername not null
);
GO

ALTER TABLE Products
ADD CONSTRAINT pk_Product_ID_ServerName PRIMARY KEY (ProductID,ServerName)
Run Code Online (Sandbox Code Playgroud)

下面的脚本将帮助您设置 T-Rep,只需更改数据库名称、目标服务器名称以及对象名称。

-- Enabling the replication database
use master
exec sp_replicationdboption @dbname = N'repl1', @optname = N'publish', @value = N'true'
GO

exec [repl1].sys.sp_addlogreader_agent @job_login = null, @job_password = null, @publisher_security_mode = 1
GO
exec [repl1].sys.sp_addqreader_agent @job_login = null, @job_password = null, @frompublisher = 1
GO
-- Adding the transactional publication
use [repl1]
exec sp_addpublication @publication = N'repl1_2005', @description = N'Transactional publication of database ''repl1'' from Publisher ''server_name\SQL2005''.', @sync_method = N'concurrent', @retention = 0, @allow_push = N'true', @allow_pull = N'true', @allow_anonymous = N'false', @enabled_for_internet = N'false', @snapshot_in_defaultfolder = N'true', @compress_snapshot = N'false', @ftp_port = 21, @ftp_login = N'anonymous', @allow_subscription_copy = N'false', @add_to_active_directory = N'false', @repl_freq = N'continuous', @status = N'active', @independent_agent = N'true', @immediate_sync = N'false', @allow_sync_tran = N'false', @autogen_sync_procs = N'false', @allow_queued_tran = N'false', @allow_dts = N'false', @replicate_ddl = 1, @allow_initialize_from_backup = N'false', @enabled_for_p2p = N'false', @enabled_for_het_sub = N'false'
GO


exec sp_addpublication_snapshot @publication = N'repl1_2005', @frequency_type = 1, @frequency_interval = 0, @frequency_relative_interval = 0, @frequency_recurrence_factor = 0, @frequency_subday = 0, @frequency_subday_interval = 0, @active_start_time_of_day = 0, @active_end_time_of_day = 235959, @active_start_date = 0, @active_end_date = 0, @job_login = null, @job_password = null, @publisher_security_mode = 1
exec sp_grant_publication_access @publication = N'repl1_2005', @login = N'sa'
GO
exec sp_grant_publication_access @publication = N'repl1_2005', @login = N'NT AUTHORITY\SYSTEM'
GO
exec sp_grant_publication_access @publication = N'repl1_2005', @login = N'BUILTIN\Administrators'
GO
exec sp_grant_publication_access @publication = N'repl1_2005', @login = N'server_name\SQLServer2005SQLAgentUser$server_name$SQL2005'
GO
exec sp_grant_publication_access @publication = N'repl1_2005', @login = N'server_name\SQLServer2005MSSQLUser$server_name$SQL2005'
GO
exec sp_grant_publication_access @publication = N'repl1_2005', @login = N'distributor_admin'
GO

-- Adding the transactional articles
use [repl1]
exec sp_addarticle @publication = N'repl1_2005', @article = N'Products', @source_owner = N'dbo', @source_object = N'Products', @type = N'logbased', @description = N'', @creation_script = N'', @pre_creation_cmd = N'none', @schema_option = 0x000000000803509F, @identityrangemanagementoption = N'none', @destination_table = N'Products', @destination_owner = N'dbo', @status = 24, @vertical_partition = N'false', @ins_cmd = N'CALL [sp_MSins_dboProducts]', @del_cmd = N'CALL [sp_MSdel_dboProducts]', @upd_cmd = N'SCALL [sp_MSupd_dboProducts]'
GO

-- Adding the transactional subscriptions
use [repl1]
exec sp_addsubscription @publication = N'repl1_2005', @subscriber = N'server_name\SQL2008R2', @destination_db = N'repl123', @subscription_type = N'Push', @sync_type = N'automatic', @article = N'all', @update_mode = N'read only', @subscriber_type = 0
exec sp_addpushsubscription_agent @publication = N'repl1_2005', @subscriber = N'server_name\SQL2008R2', @subscriber_db = N'repl123', @job_login = null, @job_password = null, @subscriber_security_mode = 1, @frequency_type = 64, @frequency_interval = 1, @frequency_relative_interval = 1, @frequency_recurrence_factor = 0, @frequency_subday = 4, @frequency_subday_interval = 5, @active_start_time_of_day = 0, @active_end_time_of_day = 235959, @active_start_date = 0, @active_end_date = 0, @dts_package_location = N'Distributor'
GO
Run Code Online (Sandbox Code Playgroud)

需要注意的几点:

在 sp_addsubscription 中确保 @sync_type = N'automatic'

并且文章属性应设置为:

在此处输入图片说明

所以最后,您可以将所有行(在我的情况下为 3 个服务器)合并,如下所示:

在此处输入图片说明

所以总结一下,

  • 使用 T-Rep。
  • 向现有发布者数据库添加一个额外的列,例如 serverName,以唯一标识订阅者处的行。
  • 在包含 PK 作为 ServerName 的 Subscriber 上创建表。

  • 使用 @sync_type = N'automatic' 和设置为“保持现有对象不变”的文章属性创建表的复制。

  • 运行快照代理。

  • 检查订阅者的合并数据。