使用多个数据库/服务器与数据进行交互


18

到目前为止,我必须处理的所有项目都只需要在单个服务器上使用一个数据库。我有兴趣了解更多有关需要扩展的项目如何迁移到多个数据库和/或服务器以帮助管理负载的信息。我知道High Scalability,但是我对一些代码示例或其他资源特别感兴趣,可以从中阅读更多有关该主题的信息。

例如:

  • 如何在多个数据库的两个表之间构造联接?(这里的代码示例会有所帮助)。
  • 是否有用于跟踪哪个数据库中的表的特殊策略?
  • 应用程序代码是否需要知道一个或多个数据库分布在多个服务器上?如果不是,则在什么级别过滤请求?
  • 什么时候可以超越1数据库/ 1服务器设置?需要这样做有多普遍?

数据库管理员可能会更好地回答此问题。不过,这里也没有什么不对劲,所以我只想检查一下DBA mod。如果适合在那里,您是否要迁移?
亚当李尔

@AnnaLear-我想这取决于答案。在这一点上,我对问题的应用程序侧更感兴趣,所以就目前而言,我认为这里可能会更好。
VirtuosiMedia

@AnnaLear ack,如果他们需要特定于应用的代码,请与OP达成协议。
jcolebrand

Answers:


13

好吧,让我们分解一下:

  • 如何在多个数据库的两个表之间构造联接?(这里的代码示例会有所帮助)。

这很简单。SQL对象具有一到四部分的命名约定:

服务器名。数据库名。架构名。表名

如果所有表都位于同一数据库的同一服务器上,并且具有相同的所有者/模式,则可以忽略前三个部分,并使用最常用的方法:

Select a.*,b.* from 
tableA a inner join 
tableB b on a.col1=b.col1

如果您的一个表位于另一个数据库中,并且两个表均使用其数据库的默认架构,则只需将数据库添加到第二个表中:

Select a.*,b.* from 
tableA a inner join 
databaseC..tableB b on a.col1 = b.col1

如果您恰巧位于与您要查询的另一个数据库都不相同的第三个数据库中,则显式使用两个数据库名称:

Select a.*,b.* from 
databaseD..tableA a inner join 
databaseC..tableB b on a.col1 = b.col1

如果最终使用了不同的模式和/或所有者,则可以在以下位置添加它们:

Select a.*,b.* from 
databaseD.john.tableA a inner join 
databaseC.accounting.tableB b on a.col1 = b.col1

最后,如果您对此非常谨慎并且有充分的理由,则可以在另一台服务器上加入一个(通常很小的)表:

Select a.* from 
databaseD.john.TableA a inner join 
ATLANTA.databaseC.accounting.tableB b on a.col1 = b.col1
  • 什么时候可以超越1数据库/ 1服务器设置?需要这样做有多普遍?是否有用于跟踪哪个数据库中的表的特殊策略?

我将两者结合起来,因为它们在一起。通常,假设一台数据库一台服务器就足够了,直到您的设计/业务/技术约束迫使您使用更多数据库时,您通常总是可以的。

因此,首先回答您的第二个问题,因为通常您都有单独的数据库的理由,所以从了解系统的设计位置应该很明显。

至于何时/为什么有必要超越单个数据库。通常,这是业务规则,政治和/或技术原因的混合。

例如,在我工作的地方,我们有16个数据库分布在4台服务器上。我们有一个MainDB,ImageDB,referencetableDB,HighvolumeTransactionDB,ReportingDB,StagingDB,ProcessingDB,ArchiveDB,FinancialDB。举例说明它们为何不同:

  • FinancialDB,敏感信息
  • 映像数据库,特定的不同存储和恢复要求
  • ReferenceDB,低事务,高读取
  • 与许多其他数据不同,ReportingDB具有很高的读取率,需要将其还原/复制到其他各种环境中
  • StagingDB,没有永久的东西,只是增强了的tempdb,我们可以更好地控制
  • MainDB,与所有其他DB接口,但需要差异备份,因此...我们将
  • HighVolumeTransaction表(相对短暂)到其自己的DB,以保持备份的合理大小。
  • 存档,来自Main和Reporting的许多相同数据,但是保留期更长,并且难以深入数据查询。如果仍然与Main / Reporting结合使用,则会使我们的系统瘫痪。

应用程序代码是否需要知道一个或多个数据库分布在多个服务器上?如果不是,则在什么级别过滤请求?

从广义上讲,它们可能会这样做。他们至少需要知道数据库连接字符串中指向的服务器。处理,报告,主要等

从那里,他们确实需要在其下执行的数据库上下文。通常,那将是该应用程序中最常用的一种,甚至可能是该应用程序的一个数据库/一台服务器中的原始版本。您可以让应用程序在每次调用时显式切换数据库上下文,但是这使得在不更改应用程序的情况下很难调整数据库。

通常(或至少是MY通常)的方法是始终通过一个或两个主要数据库进行访问。

然后根据需要在其他数据库中创建视图,并通过存储过程与数据库接口相结合。

所以来说明一下:

假设您要获取客户的人口统计信息,销售数据和贷方余额,并且这些数据最初分布在MainDB中的三个表中。

因此,您可以通过应用编写呼叫:

Select c.ClientName, c.ClientAddress, s.totalSales,f.CreditBlance from
Clients c join Sales s on c.clientid = s.clientid inner join AccountReceivable f on 
c.clientid=f.clientid where c.clientid = @clientid

太棒了 但是,现在无论何时我们更改列名或重命名/移动表,都必须更新应用程序代码。因此,我们改为做两件事:
创建客户,销售,AccountReceivables视图(您不会使用Select *,但我在这里进行演示)

Use MainDB
GO
Create view v_Clients as select * from Clients
Create view v_Sales as select * from Sales
Create view v_AccountReceivable as select * from AccountReceivable
Go

然后,我们还将创建一个存储过程spGetClientSalesAR

Create proc spGetClientSalesAR @clientID int
as
Select c.ClientName as ClientName, 
       c.ClientAddress as ClientAddress, 
       s.totalSales as TotalSales, 
       f.CreditBlance as CreditBalance 
from
v_Clients c join v_Sales s 
    on c.clientid = s.clientid 
inner join v_AccountReceivable f 
    on c.clientid=f.clientid 
where c.clientid = @clientid

并让您的应用调用它。

现在,只要不更改该存储proc上的接口,我几乎就可以对后端数据库进行任何需要扩展或扩展的操作。

在极端情况下,我什至可以使我的旧MainDB变成一堆带壳的存储过程和视图,以便在我们创建的这些视图下看起来像这样:

Create view v_Clients as select * from ServerX.DatabaseY.dbo.Clients
Create view v_Sales as select * from ServerQ.DatabaseP.dbo.Sales
Create view v_AccountReceivable as select * from ServerJ.DatabaseK.dbo.AccountReceivable

而且您的应用永远也不会知道两者之间的区别(假设快速的管道传输和良好的暂存数据等等)。

显然,这是极端的,如果我说所有事情都是以这种方式计划的,那我会撒谎,但是即使您在重构时使用存储过程/视图(即使您这样做了)也可以让您有很大的灵活性,因为您的应用程序从其谦逊的一台数据库/一台服务器成长而来开始。


TetonSig-感谢您的回答。我无法及时回复该问题,以向您授予全额赏金(我正在旅行中),但我为该问题创建了新的赏金,并将在24小时内将其授予您。
VirtuosiMedia

哇谢谢。我很感激。回答这个问题很有趣。
TetonSig

5

我在网络世界中遇到多个数据库服务器的主要方法(因为该问题被标记为PHP)是在其中设置一个“主”(写)数据库,然后是一个或多个复制的“从”(读)数据库的设置。 。数据库写入是针对“ master”数据库执行的。该数据库的内容几乎实时地复制到“从属”服务器。然后针对“从属”数据库之一运行查询(特别是密集报告),以将负载转移到这些服务器。请记住,特定的设置最适合于需要大量阅读但又不需要大量书写的应用程序。 这绝不是安排事情的唯一方法。


3

如何在多个数据库的两个表之间构造联接?(这里的代码示例会有所帮助)。

他们不是。NoSQL数据库根本不执行“联接”,即使您可以在RDBMS服务器之间进行SQL 联接,如果您重视性能(例如分布式计算的谬误),也不会希望这样做。

是否有用于跟踪哪个数据库中的表的特殊策略?

在关系/ SQL数据库中,通常使用放置在不同磁盘上的不同文件在单个服务器/数据库的范围内完成分区。从定义上说,水平扩展解决方案几乎意味着所有数据库都具有所有表,并且您具有某种事务性镜像,复制或自定义最终一致性解决方案,以确保所有数据都能到达预期的位置。

如果您实际上是在逻辑上而不是在物理拆分数据库,那么在DAL或ORM中定义的映射将声明哪个表在哪个数据库中。

NoSQL数据库是分区解决方案的组合。有时是“表”(或更常见的是“集合”)被分区了。其他时候是“行”(或“文档”)。在某些情况下,实际上是columns,例如在面向列的数据库(例如HBase)中。这完全取决于您使用的技术。所有这些的共同点是引擎本身会跟踪所有信息,因此您要做的就是索取文档或行。

当然,这是假设您实际上是在使用分片功能,而不仅仅是创建许多不同的数据库。如果您要进行后者,那您就一个人了。

应用程序代码是否需要知道一个或多个数据库分布在多个服务器上?如果不是,则在什么级别过滤请求?

如果它们是不同的逻辑数据库,则为是。如果它们仅在物理上分布,则否-假设您的特定数据库本身支持分片,或者您使用了负载平衡解决方案(用于SQL数据库)。还假设您的所有操作都是无状态的;如果要水平缩放,则必须放弃ACID。

什么时候可以超越1数据库/ 1服务器设置?需要这样做有多普遍?

是时候优化一台服务器上所有可能的一切,并且由于I / O负载的限制而无法充分发挥性能的时候了。如果您必须提这个问题,那就为时过早。

请注意,由于不良的设计,不良的索引编制,不良的查询,锁争用等原因,体面的RDBMS产品(Oracle,SQL Server)中的性能问题更为常见。这些产品可以垂直扩展到可笑的程度。所以再次重申,当您完全确定性能问题是由于硬件限制而不是仅次于标准设计/实现的结果时,应考虑“超越1个数据库/ 1个服务器设置” 。

或者,我想,某些人转而使用分布式数据库的另一个原因是,当他们不准备支付大量(或任何)钱的许可费用时,他们希望放弃SQL作为一种有意识的选择,以低成本来增加应用程序的复杂性。完全有效的理由,如果您是软件启动公司,但通常不适用于公司部门。


+1-我并不是真的在考虑NoSQL,但这同样有帮助。谢谢。
VirtuosiMedia

1

数据库有三种主要的复制配置类型:

  • 主从
  • 大师大师
  • 共识

主从示例:MySQL主服务器+ MySQL从服务器,MongoDB

Master-Master示例:CouchDB,Cassandra,Riak

共识示例:ScalienDB

...仅举几例

这些具有不同的特征。主从配置允许从节点以最大速率跟上主节点,同时非常快速地满足读取请求,而主服务器负责数据完整性。因为所有写操作都交给主服务器,所以永远不会发生锁争用,因为单个相对较慢的写程序会阻塞许多读取器,但另一方面,从属服务器最终是一致的,并且您无法获得事务隔离保证仅从大师那里读 (进一步阅读; ACID与BASE,事务隔离级别,数据库复制,MVCC /隔离:快照,事务复制)

Master-Master始终允许写操作,因此您对真实情况拥有多个权限。这可能是问题,也可能不是问题,这取决于您的应用程序正在执行的操作,但是如果您写入冲突的数据,则下次读取该键/行/列时,您可能会得到多个结果,您将这些键/行/列与应用程序逻辑和保存回数据库。(进一步阅读:CAP定理,CouchDB复制,Riak复制,一致哈希,Bitcask和StormDB,Quorum- w / MongoDB的网络拆分,合并解析策略)

跨节点复制的基于共识的数据库(例如Scalien)在写入时始终保持一致,但是以在确认写入之前交换多个消息为代价。如果您有快速的以太网并且不需要在ACK之前写入磁盘,那么这并不是什么大问题,如果您的最少三台服务器位于具有独立电源的不同服务器机架上,则不需要此操作。死亡;另外两个确保它们已保存在磁盘上)。(进一步阅读; PAXOS,PAXOS COMMIT,具有分布式事务的两阶段提交,三相提交)

其他杂项阅读:(本书:“分布式计算的元素”,向量时钟,版本向量,矩阵向量,逻辑时钟,面包店算法,间隔树时钟,参与者和反应性编程和反应堆,软件事务存储器,交易者,AKKA,Stact,分布式计算的谬论,八卦协议,Cassandra的反熵八卦协议扩展,分布式哈希表,有关在分布式环境中合并数据的论文,ZooKeeper架构,有关“异步协议”的InfoQ演示,HBase架构,MapReduce论文,Amazon Dynamo论文启动了所有NoSQL-stuff,队列,rabbitmq高可用性集群)

我希望我可以考虑一下:)。如果您也想在此推文,也可以在Twitter @henrikfeldt上关注我。


1

好的,这是关于可伸缩性的另一种观点。

让我们讨论将事物变成数据意味着什么,具有行为的含义以及具有应用程序逻辑的含义。

通常,当一个人涉足企业应用程序之类的领域时,就会接触到分层的思想。当然,分层遍及计算机中的所有位置,例如网络堆栈(ISO模型),图形(Photoshop)或SOA(服务可能称为同级或子级,但不能称为父级)。

但是,已被滥用的特定类型的分层是“ GUI”,“业务逻辑层”和“数据访问层”的分层。是的,我的意思是,这个想法原则上是好的,就像共产主义原则上是好的,但实际上并非如此。

让我们看看为什么。我要使用的参数是关于耦合的。来自一层的点触摸到另一层的点。每当您开始以人们进入的默认企业模式创建n层又称为分层应用程序时,他们会在层之间创建很多联系点。

其核心思想是层是可互换的。但事实并非如此!为什么?由于所有的呼叫现场耦合。

相反,请查看为什么网络分离!因为该接口是指向单个文件指针的字节流,所以它指向打开的套接字!ISO模型中的所有层都类似于面向对象的称为“责任链”的设计模式!每一层都包装了基础层,而不知道该基础层中数据的语义。

当数据包在底部移向以太网和原始电信号时,它被一层层连续包裹,这些层只知道自己的特定消息包络,可以发送的特定“字节批”。没什么 它不需要根据程序包的内容更改调用路径。

将此与n层进行对比,您将不得不在“呼叫”中遍历各层到数据库的路径上的“调用”更改应用程序层中的调用路径-例如,“黄金客户”是“正常客户”的超集。因此,因为我们使用“每个子表”,所以现在我们需要知道这一点,因为数据(实体)正在遍历各个层;无论是在所谓的“业务逻辑层”还是在实际进行保存的数据层中。

从计算的角度来看,它既不是可伸缩的也不是最佳的。

为什么不能扩展?因为架构是耦合的,所以您仍在尝试扩展到多个节点的旧数据库中!但是,因为您需要ACID,那个和第三个实体(数据对象),所以您需要将它们放在一个进行事务处理的数据库中!

没错,这样就消除了骚动;还有什么其他方式?

好吧,有一个讨厌的缩写叫做“ SOA”,即面向服务的体系结构。当然,世界Tomas Erls会让您实现所有层,但是要使用XML和SOAP。

由于上述所有原因,这是错误的方法,因为您将自己耦合到这些XML代理,就像您如上所述将自己耦合到应用程序层一样。

取而代之的是使用消息传递,让任何实现了消息传递功能的人都听它们。这样,您的服务界面就会变成您可以发送的消息列表,并且您尚未将操作与服务外观耦合在一起。您甚至不需要知道哪个应用程序或端点实现了这些操作,因为您所做的只是发布一条消息,表明某些其他路由机制将路由到正确的使用者!

因为您已经将服务外观与要执行的实际操作脱钩了,所以现在可以添加多个服务。实际上,这就是Netflix的做法。看一下这些演示文稿:http : //www.slideshare.net/adrianco/global-netflix-platformhttp://www.slideshare.net/adrianco/global-netflix-platform。他们很好!


0

Beta中有一个新的SQL(ACID)数据库,该数据库据称具有弹性伸缩属性。现在有一个免费的Beta程序正在运行,我建议您看看,它叫做NuoDB。

显然,即使在单线程计算机上,它也很容易胜过MySQL,但在某些基准测试中,它可以愉快地扩展到70多个实例。


单线程?那么相关基准如何?
亨里克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.