原文 http://www.sqlrepl.com/sql-server/central-subscriber-model-explained/

The majority of SQL Server Replication topologies are based on the Central Publisher model, which is comprised of a single publisher replicating to one or more subscribers.  Another replication model, which is sometimes overlooked, is the Central Subscriber model, which is comprised of multiple publishers replicating to one subscriber using Transactional Replication.

The Central Subscriber model is useful for rolling up or consolidating data from multiple sources.  Some examples include:

  • Rolling up inventory from several warehouses into a central server at corporate headquarters.
  • Sending data from remote offices within a company to a central office for business continuity.
  • Consolidating order information to one location for centralized ordering.

Priming the pump

By default, subscriptions are initialized from a snapshot generated by the Snapshot Agent and then applied by the Distribution Agent.  When the snapshot is applied, by default the article property Action if name is in use is set to Drop existing object and create a new one, which instructs that the destination table be dropped if it already exists at a subscriber.  This behavior can be problematic in the Central Subscriber model when snapshots are applied since snapshots must be applied from multiple publications.  The first snapshot is applied as expected, however, subsequent snapshot applications result in the previous snapshot data being wiped out.

The solution to this problem is horizontal partitioning, static row filters, and setting the Action if name is in use article property to Delete data. If article has a row filter, delete only data that matches the filter.

Horizontal partitioning

Ideally, published tables in a Central Subscriber topology will be horizontally partitioned.  In order to horizontally partition the tables to be published, a location-specific column should be added and included as a part of a composite primary key.  Consider a table that looks like this:

CREATE TABLE TestTable
(
ID int IDENTITY(1,1) NOT NULL,
FirstName varchar(100) NULL,
CONSTRAINT PK_TestTable_ID PRIMARY KEY CLUSTERED (ID ASC)
)

To horizontally partition TestTable and prepare it for a Central Subscriber configuration at Publisher 1, drop primary key constraint PK_TestTable_ID, add a location-specific column named LocationID with a default value of 1, and add the new composite primary key including the LocationID column.

ALTER TABLE TestTable
DROP CONSTRAINT PK_TestTable_ID
GO
 
ALTER TABLE TestTable
ADD LocationID INT NOT NULL DEFAULT(1)
GO
 
ALTER TABLE TestTable
ADD CONSTRAINT PK_TestTable_ID_LocationID PRIMARY KEY CLUSTERED (ID, LocationID)
GO

Next, to horizontally partition TestTable and prepare it for a Central Subscriber configuration at Publisher 2, the same preparation can be done with a default value of 2 for LocationID.

ALTER TABLE TestTable
DROP CONSTRAINT PK_TestTable_ID
GO
 
ALTER TABLE TestTable
ADD LocationID INT NOT NULL DEFAULT(2)
GO
 
ALTER TABLE TestTable
ADD CONSTRAINT PK_TestTable_ID_LocationID PRIMARY KEY CLUSTERED (ID, LocationID)
GO

Finally, to horizontally partition TestTable and prepare it for a Central Subscriber configuration at Publisher 3, the same preparation can be done with a default value of 3 for LocationID.

ALTER TABLE TestTable
DROP CONSTRAINT PK_TestTable_ID
GO
 
ALTER TABLE TestTable
ADD LocationID INT NOT NULL DEFAULT(3)
GO
 
ALTER TABLE TestTable
ADD CONSTRAINT PK_TestTable_ID_LocationID PRIMARY KEY CLUSTERED (ID, LocationID)
GO

Once the tables are horizontally partitioned, they can be properly published in a Central Subscriber topology by using static row filters, filtering on the LocationID column and setting the article property Action if name is in use to Delete data. If article has a row filter, delete only data that matches the filter.

Static row filters

For each article to be published in a Central Subscriber topology, a static row filter should be defined to leverage the Action if name is in usearticle property appropriately.  A static row filter uses a WHERE clause to select the data to be published.  To publish rows from Publisher 1, specify LocationID = 1 for the filter clause. Likewise, to publish rows from Publisher 2 and Publisher 3, specify LocationID = 2 and LocationID = 3 for the filter clause, respectively.

Action if name is in use

When creating the publications and adding articles, the article property Action if name is in use needs to be set to Delete data. If article has a row filter, delete only data that matches the filter.  This can be set using the New Publication Wizard Article Properties dialog or by using replication stored procedures sp_addarticle and specifying a value of delete for the @pre_creation_cmd argument.  This way, when the central subscriber is initialized or reinitialized from multiple publication snapshots, previously applied snapshot data will be preserved since only data matching the filter clause will be deleted.

The caveat

As we can see, horizontal partitioning requires that tables have a location-specific column added, however, the location-specific column does not necessarily need to be included as a part of the primary key at the publication databases.  In addition, it is not a hard requirement that published tables in a Central Subscriber topology be horizontally partitioned.  In some shops, changing a primary key or adding additional columns is strictly prohibited, in which case I would urge you to take an alternative approach.  If you would like some ideas on implementing a Central Subscriber topology without modifying primary keys or horizontally partitioning publication databases, feel free to get in touch or leave a comment below.

Central Subscriber Model Explained的更多相关文章

  1. AMQP 0-9-1 Model Explained Why does the queue memory grow and shrink when publishing/consuming? AMQP和AMQP Protocol的是整体和部分的关系 RabbitMQ speaks multiple protocols.

    AMQP 0-9-1 Model Explained — RabbitMQ http://next.rabbitmq.com/tutorials/amqp-concepts.html AMQP 0-9 ...

  2. [Windows Azure] Building the web role for the Windows Azure Email Service application - 3 of 5

    Building the web role for the Windows Azure Email Service application - 3 of 5. This is the third tu ...

  3. [转]Design Pattern Interview Questions - Part 2

    Interpeter , Iterator , Mediator , Memento and Observer design patterns. (I) what is Interpreter pat ...

  4. OpenStack 企业私有云的若干需求(10):OpenStack 的前景和钱景

    本系列会介绍OpenStack 企业私有云的几个需求: 自动扩展(Auto-scaling)支持 多租户和租户隔离 (multi-tenancy and tenancy isolation) 混合云( ...

  5. Lock-Free 编程

    文章索引 Lock-Free 编程是什么? Lock-Free 编程技术 读改写原子操作(Atomic Read-Modify-Write Operations) Compare-And-Swap 循 ...

  6. 关于 ActiveMQ 的消息模式

    1.JMS Queue 执行 load balancer语义:一条消息仅能被一个 consumer(消费者) 收到.如果在 message 发送的时候没有可用的consumer,那么它将被保存一直到能 ...

  7. Mingyang.net:用注解校验数据

    注解校验依赖的是javax.validation和hibernate-validaton. <dependency> <groupId>javax.validation< ...

  8. ActiveMQ使用总结

    一.下载使用: 官网下载apache-activemq-5.8.0-bin.tar.gz.apache-activemq-5.8.0-bin.zip 解压,然后启动ActiveMQ服务器 方法1: 直 ...

  9. JMS理解2

    使用JMS 的应用程序被称为JMS 客户端,处理消息路由与传递的消息系统被称为JMS Provider,而JMS 应用则是由多个JMS 客户端和一个JMS Provider 构成的业务系统.发送消息的 ...

随机推荐

  1. C++ 指向类成员函数指针的用法(转自维基百科)

    类成员函数指针 类成员函数指针(member function pointer),是C++语言的一类指针数据类型,用于存储一个指定类具有给定的形参列表与返回值类型的成员函数的访问信息. 目录 1 语法 ...

  2. 算法 Tricks(五)—— 二进制逻辑运算

    int flag = 1; while ( (data & flag) == 0 ) flag <<= 1; 判断某数的二进制形式的某位(第 k 位)是否为 1,将其与 2k 相与 ...

  3. OSGi开发环境的建立

    1 OSGi开发环境的建立 1.1 Equinox是什么 从代码角度来看,Equinox其实就是OSGi核心标准的完整实现,并且还在这个基础上增加了一些额外的功能(比如为框架增加了命令行和程序执行的入 ...

  4. 【codeforces 768B】Code For 1

    [题目链接]:http://codeforces.com/contest/768/problem/B [题意] 一开始给你一个数字n; 让你用这个数字n根据一定的规则生成序列; (如果新生成的序列里面 ...

  5. Qt多线程和GUI界面假死(run()是线程的入口,就像main()对于应用程序的作用。分析QThread::exec函数的源码,旧的QMutexLocker模式其实很好用,挡住别人进入抢占资源,可照抄)good

    QThread的常见特性: run()是线程的入口,就像main()对于应用程序的作用.QThread中对run()的默认实现调用了exec(),从而创建一个QEventLoop对象,由其处理该线程事 ...

  6. 关于Vuex可直接修改state问题

    下面的代码证明不通过mutation,而直接修改state修改确实生效了.这样子多人协作岂不是很容易出问题.对于这个问题,在创建 store 的时候传入 strict: true, 开启严格模式,那么 ...

  7. docker部署netcore应用(二)

    基于第一章已经安装好了docker,这次将把netcore应用部署到docker容器中 开发工具vs2017,准备个DotNet Core的Console应用程序,测试一下 发布DockerTest项 ...

  8. 前端后端分离,怎么解决SEO优化的问题呢?

    对于90%以上的互联网公司来说,前后端分离是必须要做的.目前接手的公司的一个工程,后端是PHP,用的smarty模板,开发效率和之前公司的完全分离相比,确实低不少,一方面需要前端会PHP,另一方面沟通 ...

  9. opencc 繁体简体互转 (C++)

         繁体字通常采用BIG5编码,简体字通常采用GBK或者GB18030编码,这种情况下,直接使用iconv(linux下有对应的命令,也有对应的C API供编程调用)就行.对于默认采用utf-8 ...

  10. TstringBuilder Delphi2007版

    2010中的StringBuilder对象用的比较爽快!于是稍作了一些修改(增加了几个函数和属性)然后移植到D2007中来使用了!效果不错,共享一下! unit DxStringBuilder; in ...