2013-05-04 185 views
21

我试图解决一个问题,那一次,我没有创建。在SQL数据库之间共享数据

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

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

我想抽象出这个公共数据到单个数据库,但仍然让其他数据库加入这些表,甚至有键强制约束等......我在MsSql环境中。

enter image description here

哪些可供选择?就我看到它,我有以下选择:

  • 链接服务器
  • 只读登录授予访问权限的意见

还有什么考虑?

+0

您打算如何使用这些信息?您可以创建一个数据库来保存其他数据库的公共信息。使用mySQL ETL工具将数据从应用程序数据库位置移动到一个集中式数据库。我认为Pentaho水壶应该允许你对你的应用数据库的影响很小。 – Zane 2013-05-06 19:35:05

+0

对不起,我误读了你没有使用mySQL的标签。这使事情变得更容易。 – Zane 2013-05-06 19:43:44

+0

您对使用SSIS有多熟悉? – Zane 2013-05-06 19:44:04

回答

21

有很多方法可以解决这个问题。我强烈建议,要么取决于您的业务解决方案,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个以上的异步镜像。除非您计划使用镜像进行灾难恢复,否则您不想为此使用同步镜像。如果您希望有多个单独的应用程序需要来自单个中央数据库的数据,那么您可能需要考虑像IBM Web Sphere,Microsoft BizTalk,Vitria,TIBCO等企业消息传递系统。这些应用程序是专为解决这个问题而打造。他们往往是昂贵和繁琐的实施和维护,但他们可以扩大如果你有全球分布式系统或几十个单独的应用程序,都需要在一定程度上共享数据。

  3. 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没有足够的关于链接服务器的统计信息,因此会产生非常糟糕的查询计划。链接服务器对于某些特定场景可能很有用,但建议围绕此功能构建对中央数据库的访问权限,尽管技术上可行,但不推荐使用。

  4. 批量ETL过程:如果Web应用程序的延迟时间很长,则可以使用SSIS (lots of good links in this StackOverflow question)编写批量ETL过程,这些过程由SQL Server代理作业执行以在服务器之间移动数据。还有其他替代ETL工具,如Informatica,Pentaho等,因此请使用最适合您的工具。

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

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

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

+0

所有这些伟大的作品。我会进一步讨论为什么链接服务器是讨厌的:http://stackoverflow.com/a/4091984/2424 – NotMe 2013-05-06 20:33:25

2

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

1

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

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建议的方法实际移动数据。

如果你去链接服务器的路线,我会建议reading upOPENQUERY。在OPENQUERY vs 4部分标识here上有一篇很好的文章。

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 

当然,需要注意的是,如果你在中央表中删除引用的记录,你不会得到一个错误是很重要的。