每个客户端使用单个数据库有什么好处?

在为多个客户端devise的以数据库为中心的应用程序中,我一直认为对所有客户端使用单个数据库是“更好的” – 将logging与正确的索引和键相关联。 在听Stack Overpod播客时,我听到Joel提到FogBugz每个客户端使用一个数据库(所以如果有1000个客户端,则会有1000个数据库)。 使用这种架构的优点是什么?

我明白,对于一些项目,客户端需要直接访问他们的所有数据 – 在这样的应用程序中,显然每个客户端都需要自己的数据库。 但是,对于客户端不需要直接访问数据库的项目,每个客户端使用一个数据库是否有优势? 从灵活性的angular度来看,使用单个数据库和表的单个副本要简单得多。 添加新function更容易,创build报告更容易,pipe理起来更简单。

我对“所有客户端的一个数据库”方法非常有信心,直到我听说Joel(一位有经验的开发人员)提到他的软件使用了不同的方法 – 我对他的决定有点困惑…

我曾经听到有人说数据库有大量的logging会减慢速度,但是任何有一些优点的关系数据库都不会有这个问题 – 特别是如果使用了合适的索引和键的话。

任何input,非常感谢!

假设将所有客户端存储在一个数据库中不存在缩放惩罚; 对于大多数人来说,以及configuration良好的数据库/查询,这些日子将会是相当真实的。 如果你不是这些人中的一员,那么单个数据库的好处是显而易见的。

在这种情况下,好处来自每个客户端的封装。 从代码的angular度来看,每个客户端都是孤立存在的 – 数据库更新不可能覆盖,损坏,检索或更改属于另一个客户端的数据。 这也简化了模型,因为您不需要考虑logging可能属于另一个客户的事实。

您还可以获得可分离性的好处 – 将与给定客户端关联的数据提取出来并将其移至不同的服务器是很简单的。 或者在调用“使用内置数据库机制来删除一些关键数据!”时恢复该客户机的备份。

您可以轻松获得免费的服务器移动性 – 如果超出一台数据库服务器的范围,则可以在另一台服务器上托pipe新的客户端。 如果他们都在一个数据库中,则需要更强大的硬件,或者在多台机器上运行数据库。

您可以轻松进行版本控制 – 如果一个客户想要保留在软件版本1.0上,而另一个客户想要2.0,而1.0和2.0使用不同的数据库模式,则没有任何问题 – 您可以迁移一个,而无需从一个数据库中提取出来。

我猜想还有几十个。 但总而言之,关键概念是“简单”。 该产品pipe理一个客户端,因此pipe理一个数据库。 从“数据库还包含其他客户端”的问题决不会有任何复杂性。 它符合用户的心智模式,他们独自存在。 像能够简单地向所有客户报告一样的优势是微乎其微的 – 您希望多长时间一次向全世界报告,而不仅仅是一个客户?

保持简单。 您可以确定您的客户端只能看到他们的数据。 logging较less的客户不必支付与可能在数据库中但不是他们的数十万条logging竞争的处罚。 我不在乎一切都索引和优化,会有一些查询,确定他们必须扫描每个logging。

以下是我见过的一种方法:

  • 每个客户都有一个唯一的连接string存储在主客户数据库中。
  • 数据库的devise使所有的东西都按照CustomerID分割,即使数据库上有一个客户。
  • 如果需要,创build脚本将所有客户数据迁移到新的数据库,然后只有客户的连接string需要更新以指向新的位置。

这允许一开始就使用单个数据库,一旦拥有大量客户端,或者更常见的情况下,当您有一些过度使用系统的客户时,可以轻松地进行分段。

我发现当所有的数据都在同一个数据库中时,恢复特定的客户数据是非常困难的,但是pipe理升级要简单得多。

当每个客户使用一个数据库时,遇到一个巨大的问题,就是让所有的客户都在相同的模式版本上运行,甚至不考虑一大堆客户特定的数据库上的备份工作。 自然地恢复数据是比较容易的,但是如果你确保不要永久删除logging(只需标记一个删除的标志或移动到一个归档表),那么你首先就不需要数据库恢复。

至于一次升级1000台数据库服务器的痛苦,一些相当简单的自动化应该考虑到这一点。 只要每个数据库保持一个相同的模式,那么它不会是一个问题。 我们也使用每个客户端的数据库方法,并且对我们来说效果很好。

这里是关于这个确切的主题(是的,这是MSDN,但它是一个技术独立的文章)的文章: http : //msdn.microsoft.com/en-us/library/aa479086.aspx 。

关于多租户的另一个讨论,因为它涉及到您的数据模型在这里: http : //www.ayende.com/Blog/archive/2008/08/07/Multi-Tenancy–The-Physical-Data-Model.aspx

那么,如果你的一个客户告诉你,由于一些粗糙的导入工作或类似情况,还原到他们的数据的早期版本? 想象一下,如果你告诉他们“你不能那么做,因为你的数据是在我们所有的客户端之间共享的”,或者“对不起,但是你的改变丢失了,因为客户端X要求恢复数据库”。

可扩展性。 安全。 我们公司每个客户也使用1个DB。 这也使代码更容易维护。

感谢您的input – 所有优秀和非常有效的点。 我想我更看重升级的灵活性。 如果您需要修改模式以添加新function(可以说是针对Web应用程序),还是要增强现有function,则在单个数据库中执行操作很简单。 如果您不得不在1000个不同的数据库中复制此更改,则错误的可能性会增加。 如果操作失败怎么办? 升级每个客户需要多长时间?

如果保留了适当的备份(或者如果数据库的结构是从未实际覆盖数据的话),为特定客户端恢复数据是微不足道的。

代码的简单性虽然很重要,但并不真正变得非常复杂。 根据所使用的语言和方法,很容易创build只代表特定客户端(存储特定客户端ID)的对象,其余项目只需要为单个对象进行编码(有点像单个客户端)。

可扩展性是需要考虑的事情 – 你说对了,把一个单独的数据库移动到另一个物理服务器是很容易的。 然而,将服务器集中在一起变得越来越容易 – 即使没有集群,看起来将每个客户端指向承载通用数据库的数据库SERVER也是一个小改变(因此,您可以有两个或三个数据库服务器托pipe例如每个只有一个数据库)。 这种方法使升级过程仅限于三个数据库。

我只是添加这个答案,在这里包括多租户这个词。 我正在寻找这个,使用“multitenant”作为查询,这一个没有出现。

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

升级时更新多个数据库的简单答案是将升级作为事务进行,并在必要时升级之前创build快照。 如果您正在运行您的操作,那么您应该能够将升级应用到任意数量的数据库。

集群并不是真正的索引和全表扫描问题的解决scheme。 如果你转移到一个集群,很less有变化。 如果你有许多较小的数据库分布在多台机器上,你可以更便宜地做到这一点,没有一个集群。 可靠性和可用性是考虑因素,但可以通过其他方式处理(有些人仍然需要集群,但大多数人可能不需要)。

我有兴趣从这里听到更多的背景信息,因为集群不是一个简单的话题,而且在RDBMS世界中的实现也很昂贵。 关于在非关系型世界Google Bigtable等中的聚类有很多谈论/虚张声势,但是他们正在解决一系列不同的问题,并且失去了RDBMS的一些有用的特性。

“数据库”有几个含义,

  • 硬件盒
  • 正在运行的软件(如“oracle”)
  • 特定的一组数据文件
  • 特定的login或架构

Joel可能意味着其中一个较低的层次。 在这种情况下,这只是软件configurationpipe理的问题…例如,您不必修补1000个软件服务器来修复安全性问题。

我认为这是一个好主意,所以软件错误不会泄漏客户端的信息。 想象一下错误的where子句,告诉我你的客户数据和我自己的数据。