对每个客户端使用单个数据库有什么优势?


67

在针对多个客户端设计的以数据库为中心的应用程序中,我一直认为将单个数据库用于所有客户端是“更好”的选择-将记录与正确的索引和键相关联。在听Stack Overflow播客时,我听到Joel提到FogBugz每个客户端使用一个数据库(因此,如果有1000个客户端,则将有1000个数据库)。使用这种架构的优势是什么?

我知道对于某些项目,客户需要直接访问其所有数据-在这样的应用程序中,很明显每个客户都需要自己的数据库。但是,对于不需要客户端直接访问数据库的项目,每个客户端使用一个数据库有什么好处?从灵活性的角度来看,使用具有单个表副本的单个数据库要简单得多。添加新功能更容易,创建报表也更容易,管理也更容易。

在听到Joel(经验丰富的开发人员)提到他的软件使用不同的方法之前,我对“为所有客户提供一个数据库”方法非常有信心,并且我对他的决定有些困惑...

我听说人们援引数据库速度慢,但记录数量众多,但是任何具有某些优点的关系数据库都不会出现此问题-特别是如果使用正确的索引和键。

任何输入,不胜感激!


3
另请参阅serverfault中的一个数据库与多个数据库
与OrjanJämte

Answers:


48

假设将所有客户端存储在一个数据库中没有扩展成本;对于大多数人来说,配置良好的数据库/查询,如今确实如此。如果您不是这些人中的一员,那么单个数据库的好处显而易见。

在这种情况下,受益于每个客户端的封装。从代码角度来看,每个客户端都是孤立存在的-在任何情况下,数据库更新都不会覆盖,破坏,检索或更改属于另一个客户端的数据。这也简化了模型,因为您无需考虑记录可能属于另一个客户端这一事实。

您还将获得可分离性的好处-提取与给定客户端关联的数据,然后将其移动到其他服务器是很简单的。或者使用内置的数据库机制在调用“我们已经删除了一些关键数据!”时恢复该客户端的备份。

您可以轻松自由地移动服务器-如果您扩展一台数据库服务器的规模,则可以在另一台服务器上托管新客户端。如果它们都在一个数据库中,则您需要获得更强大的硬件,或者在多台计算机上运行数据库。

您可以轻松地进行版本控制-如果一个客户端希望使用软件版本1.0,而另一个客户端希望使用2.0,而1.0和2.0使用不同的数据库模式,则没有问题-您可以迁移一个而不必将它们拉出一个数据库。

我想我还能想到几十个。但总的来说,关键概念是“简单性”。该产品管理一个客户,因此管理一个数据库。“但是数据库还包含其他客户端”问题从没有任何复杂性。它适合用户的心理模型,他们一个人存在。能够一次轻松地对所有客户进行报告的优势是微乎其微的-您希望多久一次报告整个世界,而不仅仅是一个客户?


3
就保持客户端之间的“隔离墙”而言,这就是存储过程和触发器的用途(警告:不建议用于MySQL)-如果已经构建了客户端的数据,则将客户端的数据(重新)移动到不同的服务器也非常容易。模式正确。“简单性”也相反。如果我只有一个数据库,则可以轻松地合并我的连接并简化该代码。如果连接用完了,我只会增加池。无需分别监视每个客户端。
BryanH

14

这是我以前见过的一种方法:

  • 每个客户都有一个唯一的连接字符串,存储在主客户数据库中。
  • 数据库的设计使所有内容都按CustomerID进行了细分,即使数据库上只有一个客户也是如此。
  • 如果需要,将创建脚本以将所有客户数据迁移到新数据库,然后仅需要更新该客户的连接字符串以指向新位置。

这样一来,您可以先使用一个数据库,然后在拥有大量客户之后便可以轻松地进行分段,或者当您有几个过度使用系统的客户时更容易进行分段。

我发现,当所有数据都在同一数据库中时,还原特定客户数据确实很困难,但是管理升级要简单得多。

当每个客户使用一个数据库时,您会遇到一个巨大的问题,那就是使所有客户都运行在相同的架构版本上,甚至不考虑在整个客户特定数据库上的备份作业。自然地恢复数据比较容易,但是如果您确保不永久删除记录(只需标记一个已删除的标志或移至存档表),那么首先就不需要数据库还原。


11

为了简单起见。您可以确定您的客户只看到他们的数据。记录少的客户端不必为必须与数据库中可能存在的数十万条记录竞争而不必与之竞争的代价。我不在乎所有索引和优化的程度如何,会有查询确定它们必须扫描每条记录。


事实并非如此。如果您不能使用索引来隔离行,则可能是数据库设计不佳,或者您正在尝试查询整个跨客户数据集,而从一开始就很难做到。
尼克,

10

好吧,如果您的一个客户告诉您由于某些错误的导入工作或类似原因而还原到其数据的较早版本怎么办?想象一下,如果您告诉客户“由于所有客户之间都共享数据,您将无法做到”或“对不起,但是您的更改丢失了,因为客户X要求还原数据库”,您的客户会有什么样的感受。


2
所有表应按TenantID分区。这使您可以仅备份/还原一个客户端的分区:)
dariol 2010年

@ dario-g:听起来您正在支持共享数据库方法。请解释一下按TenantID分区的含义,因为这可能并不明显。
Gruber 2012年

1
在Oracle中,您可以对表进行分区并将分区移动到远程位置,但是您仍然只有一个表。
givanse 2014年

9

至于一次升级1000个数据库服务器的痛苦,应该使用一些相当简单的自动化来解决。只要每个数据库都维护相同的架构,就不会真正成为问题。我们还使用每个客户方法使用数据库,因此对我们来说效果很好。

这是有关此确切主题的文章(是的,它是MSDN,但它是与技术无关的文章):http : //msdn.microsoft.com/zh-cn/library/aa479086.aspx

关于与您的数据模型相关的多租户的另一讨论:http : //www.ayende.com/Blog/archive/2008/08/07/Multi-Tenancy--The-Physical-Data-Model.aspx


2
谁知道有一种工具可以自动升级多个数据库,例如MySQL?如果决定使用隔离方法,则需要确保1000个数据库是最新的,并镜像指定的master数据库的架构。
Gruber 2012年

1
@Nathan,您还在为每个租户使用一个数据库吗?
jonathancardoso

1
不,最终只有一个多租户数据库,并将租户隐私放入应用程序框架。每个租户一个数据库对我们来说是太多的开销。
内森

6

可扩展性。安全。我们公司的每个客户方法也使用1 DB。它还使代码也易于维护。


2
嘿,您还在使用这种方法吗?您是否愿意分享一些有关当前有多少个客户端/数据库的数字?
jonathancardoso


3

感谢您的输入-所有非常有效的观点。我想我正在寻找更多的升级灵活性。如果您需要修改架构以添加新功能(对于Web应用程序来说)或增强现有功能,则在单个数据库中进行操作很简单。如果必须在1000个单独的数据库中复制此更改,则出错的机会会增加。如果操作失败怎么办?升级每个客户端需要多长时间?

如果保留正确的备份(或者如果数据库的结构从未真正覆盖过数据),则为特定客户端还原数据将变得很简单。

代码的简单性虽然很重要,但实际上并没有变得非常复杂。根据所使用的语言和方法,创建仅代表特定客户端(存储特定客户端ID)的对象很简单,而项目的其余部分仅需为单个对象编码(类似于单个客户端) )。

可伸缩性是要考虑的问题-您说对了,将单个隔离的数据库移至其他物理服务器很容易,这是正确的。但是,将服务器群集在一起变得越来越容易-即使没有群集,将每个客户端指向托管通用数据库的数据库SERVER似乎也是一个小小的更改(因此,您可以拥有两个或三个数据库服务器来托管例如,每个数据库只有一个)。这种方法使升级过程仅限于三个数据库。


3
您似乎倾向于共享方法。我和你在一起。
Matt Kocaj 09年

2

在诸如医疗保健之类的受监管行业中,可能需要每个客户一个数据库,甚至可能需要一个单独的数据库服务器。

升级时更新多个数据库的简单答案是将升级作为事务进行,并在必要时进行快照,然后再进行升级。如果运行良好,则应该可以将升级应用于任何数量的数据库。

群集实际上并不是解决索引和全表扫描问题的解决方案。如果移至群集,则几乎不会有任何变化。如果您有许多较小的数据库要分布在多台计算机上,则可以在没有群集的情况下更便宜地进行此操作。可靠性和可用性是考虑因素,但可以通过其他方式处理(某些人仍将需要集群,但大多数人可能不需要)。

我有兴趣听取您的更多背景信息,因为集群不是一个简单的话题,并且在RDBMS世界中实现起来很昂贵。在非关系世界Google Bigtable等中,有很多关于集群的讨论/讨论。但是它们正在解决一系列不同的问题,并且失去了RDBMS的一些有用功能。


0

“数据库”有两个含义

  • 五金盒
  • 正在运行的软件(例如“ oracle”)
  • 特定的数据文件集
  • 特定的登录名或架构

Joel可能是较低层之一。在这种情况下,这仅是软件配置管理的问题……例如,您不必修补1000个软件服务器即可修复安全漏洞。

我认为这是个好主意,因此,软件错误不会在客户端之间泄漏信息。想象一下带有错误的where子句的情况,该子句可以向我显示您的客户数据以及我自己的客户数据。


4
不,他指的是数据库。发出“ CREATE DATABASE”语句时创建的事物。
BobbyShaftoe
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.