在SQL数据库之间共享数据

时间:2013-05-04 04:33:05

标签: sql-server database linked-server data-exchange

我正试图解决一个问题,一次,我没有创造。

我在不同服务器上由不同数据库支持的许多Web应用程序的环境中工作。

每个数据库在设计和应用方面都相当独特,但每个数据库中仍然存在我想要抽象出来的常见数据。例如,每个数据库都有供应商表,用户表等......

我想将这个常见数据抽象到单个数据库中,但仍然让其他数据库加入这些表,甚至还有密钥来强制执行约束等等......我在MsSql环境中。

enter image description here

有哪些选择?我看到它的方式,我有以下选择:

  • 已关联的服务器
  • 只读登录以提供对视图的访问权

还有什么需要考虑的吗?

5 个答案:

答案 0 :(得分:25)

有很多方法可以解决这个问题。我强烈推荐解决方案1,2或3,具体取决于您的业务需求:

  1. Transactional Replication:如果公共数据库是帐户记录,并且您希望为单独的应用程序提供数据的只读版本,那么您可以复制核心表,甚至可能只是核心表表的列,到每个单独的服务器。这种方法的一个好处是您可以根据需要复制到任意数量的订户数据库。这也意味着您可以根据需要自定义订阅者可以使用的表和字段。因此,如果一个应用程序需要用户表而不是供应商表,那么您只需订阅用户表。如果另一个只需要供应商表而不需要用户表,那么您只能订阅供应商表。另一个好处是复制保持自身同步,如果出现问题,您可以随时重新初始化订阅。

    我使用事务复制从数据仓库中推出超过100个表,以分离需要访问来自多个系统的聚合数据的下游应用程序。由于我们的数据仓库是按镜像和日志传送数据源按小时计划更新的,因此生产应用程序在每小时20到80分钟的滑动窗口内有来自众多系统的数据。

    Peer-to-Peer transactional replication作为发布类型可能更适合您提供的用例。如果要逐节点地逐步推出架构或复制更改,这可能非常有用。标准事务复制在这方面有一些限制。

    快照复制发布类型比事务发布具有更多延迟,但如果可以接受一定程度的延迟,您可能需要考虑它。

    虽然您提到您是Microsoft SQL Server商店,但请记住其他RDBM具有类似的技术。由于您专门讨论MS SQL Server,请注意事务复制也允许您复制到Oracle数据库。因此,如果您的组织中有一些这样的解决方案,那么此解决方案仍然有效。

    使用事务复制的一个缺点是,如果中央服务器出现故障,您可能会在复制对象的下游副本中遇到数据延迟。如果复制的对象(文章)非常大并且您需要重新初始化表格,那么这也需要很长时间才能完成。

  2. Mirrors:如果要在下游服务器上实时访问数据库,可以设置最多两个异步镜像。我以这种方式将数据与CRM应用程序集成在一起。所有读取都来自镜像的连接。所有写入都被推送到消息队列,然后将更改应用到中央生产服务器。这种方法的缺点是你不能创建2个以上的异步镜像。除非您计划使用镜像进行灾难恢复,否则您不希望将同步镜像用于此目的。

  3. Messaging Systems:如果您希望有许多单独的应用程序需要来自单个中央数据库的数据,那么您可能需要考虑企业消息传递系统,如IBM Web Sphere,Microsoft BizTalk,Vitria,TIBCO,这些应用程序专门用于解决此问题。它们往往是昂贵且实施和维护繁琐,但如果你有全球分布式系统或几十个单独的应用程序都需要在一定程度上共享数据,它们可以扩展。

  4. Linked Servers:听起来你已经想到了这个。您可以通过链接服务器公开数据。我不相信这是一个很好的解决方案。如果您真的想要使用此路由,请考虑设置从中央数据库到另一台服务器的异步镜像,然后设置与镜像的链接服务器连接。这至少可以降低来自Web应用程序的查询将导致中央生产数据库出现阻塞或性能问题的风险。

    IMO,链接服务器往往是一种共享应用程序数据的危险方法。此方法仍将数据视为数据库中的二等公民。这导致一些非常糟糕的编码习惯,特别是因为您的开发人员可能使用不同的连接方法在不同语言的不同服务器上工作。你不知道是否有人会针对你的核心数据写一个真正有意义的查询。如果您设置的标准需要将共享数据的完整副本下载到非核心服务器,那么您不必担心开发人员是否编写了错误的代码。至少从他们糟糕的代码不会使其他编写良好的系统的性能变得不利的角度来看。

    有很多很多资源可以解释为什么在这种情况下使用链接服务器会很糟糕。非详尽的原因列表包括:(a)the account used for the linked server must have DBCC SHOW STATISTICS permissions or the queries will not be able to make use of existing statistics,(b)除非作为OPENQUERY提交,否则不能使用查询提示,(c)在使用时不能传递参数OPENQUERY,(d)服务器没有足够的关于链接服务器的统计数据,因此,创建了非常糟糕的查询计划,(e)网络连接问题可能导致失败,(f)any one of these five performance issues和(g) )the dreaded SSPI context error when trying to authenticate windows active directory credentials in a double hop scenario。链接服务器对某些特定方案很有用,但建议不要在技术上允许的情况下围绕此功能构建对中央数据库的访问权。

  5. 批量ETL过程:如果Web应用程序可接受高度延迟,那么您可以使用SSIS (lots of good links in this StackOverflow question)编写批量ETL过程,这些过程由SQL Server代理作业执行以在服务器之间移动数据。还有其他替代ETL工具,如Informatica,Pentaho等,所以使用最适合你的方法。

    如果您需要低延迟,这不是一个好的解决方案。在与第三方托管的CRM解决方案同步时,我已经使用此解决方案来处理可以容忍高延迟的字段。对于无法容忍高延迟(基本帐户创建数据)的字段,我们依赖于在帐户生成时通过Web服务调用在CRM中创建重复记录。

  6. 每夜备份和还原:如果您的数据可以容忍高延迟(最多一天)和不可用时段,那么您可以跨环境备份和还原数据库。对于需要100%正常运行时间的Web应用程序,这不是一个好的解决方案。我们的想法是您进行基线备份,将其还原为单独的还原名称,然后在新数据库准备好使用后立即重命名原始数据库和新数据库。我已经看到这对一些内部网站应用程序已经完成,但我一般不推荐这种方法。这更适合较低的开发环境,而不适合生产环境。

  7. Log Shipping Secondaries:您可以在主要和任意数量的辅助设备之间设置日志传送。这类似于夜间备份和还原过程,但您可以更频繁地更新数据库。在一个实例中,该解决方案用于通过在两个日志传送接收者之间切换来从下游用户的一个主要核心系统公开数据。有另一台服务器指向这两个数据库,并在新数据库可用时在它们之间切换。我真的很讨厌这个解决方案,但有一次我看到这个实现它确实满足了业务需求。

答案 1 :(得分:2)

您还可以考虑在公共数据存储和应用程序DB之间使用内置SQL Server复制。根据我的经验,它非常适合双向数据传输,每个数据库中都有一个表的实例,可以使用外键(我不认为FK可以通过链接服务器实现)。

答案 2 :(得分:2)

可能还有其他选择,但认为您是使用链接服务器和视图组合的最佳选项的正确途径。这可以像创建新数据库,添加两个链接服务器,设置权限然后创建必要视图一样简单。

如果你的目标是abstract out this common data to a single database but still let the other databases join on these tables, even have keys to enforce constraints,那么此解决方案应该可以正常工作。

在不利方面,您可能会遇到链接服务器的性能问题,因此如果您预见到数据库会获得大量流量,那么您可能希望使用Doug或mwebber建议的方法来实际移动数据。

如果你去了链接服务器路线,我会在OPENQUERY上推荐reading up。关于OPENQUERY与4部分标识符here的文章很好。

答案 3 :(得分:1)

看看Microsoft Sync Framework。您必须编写同步应用程序,但它可能会为您提供所需的灵活性。

答案 4 :(得分:1)

我认为你应该好好看看复制,正如许多答案所说的那样,特别是在高TPS环境中,或者你想要在许多表上使用它。但是,我将提供一些代码,说明如何使用链接服务器,同义词和检查约束在我的某些系统中实现您的既定目标。

  

我想将这个常见数据抽象到单个数据库中,但仍然允许其他数据库加入这些表,甚至还有用于强制执行约束的键等等。

您可以将数据库中的视图或synonym设置为链接服务器(或其他本地数据库)中的公用表。如果视图只是select * from table,我更喜欢同义词。

如果您有权限,表同义词将允许您在远程项目上运行DML。

但是,此时,您的视图或同义词不能使用外键,但我们可以使用检查约束来完成类似的操作。

让我们看一些代码:

create synonym MyCentralTable for MyLinkedServer.MyCentralDB.dbo.MyCentralTable
go

create function dbo.MyLocalTableFkConstraint (
    @PK int
)
returns bit
as begin
    declare @retVal bit
    select @retVal = case when exists (
                            select null from MyCentralTable where PK = @PK
                        ) then 1 else 0 end
    return @retVal
end
go

create table MyLocalTable (
    FK int check (dbo.MyLocalTableFKConstraint(FK) = 1)
)
go

-- Will fail: -1 not in MyLinkedServer.MyRemoteDatabase.dbo.MyCentralTable
insert into MyLocalTable select -1
-- Will succeed: RI on a remote table w/o triggers
insert into MyLocalTable select FK from MyCentralTable

当然,重要的是要注意,如果删除中心表中的引用记录,则不会出现错误。