我应该为多客户端应用程序使用单个数据库设置还是多个数据库设置?

66

我正在开发一个PHP应用程序,旨在简化公司的工作流程和项目管理,可以说类似于BasecampGoPlan

就数据库而言,我不确定最佳方法是什么。我应该使用单个数据库,并将特定于客户的列添加到每个表中,还是应该为每个新客户创建一个数据库?一个重要因素是自动化:我希望创建新客户(并可能开放自己注册的可能性)变得非常简单。

我能想到使用单个数据库的一些潜在缺点:

  • 可扩展性不足
  • 安全问题(尽管缺陷本来就不应该存在

你对此有何想法?你有任何关于上述公司最可能选择的解决方案的想法吗?


我有同样的问题。这是我得到的一些答案。 https://dev59.com/o3VD5IYBdhLWcg3wKYL- 请查看LinkedIn架构的幻灯片。 - Vyrotek
速度是否也被考虑在内了呢?拥有100万条记录的数据库搜索性能明显优于10亿条记录的搜索。我很好奇你在这方面表现如何。 - JM4
9个回答

38
我通常会在所有表格中添加客户端ID,并使用一个数据库。但是,由于数据库通常很难扩展,我还将使其能够在某些或所有客户端的不同数据库实例上运行。 这样,您就可以在一个数据库中拥有一堆小客户端和独立服务器上的大客户端。 然而,可维护性的关键因素是保持所有数据库中的模式相同。管理版本控制已经足够头疼了,不要引入特定于客户端的模式。

4
是的,这是一种分片的典型例子。您还可以将客户端移动到不同的数据库进行维护等操作。关键是构建工具来移动数据并创建API以查找帐户所在的服务器。一旦完成,就没有限制了。 - Gary Richardson

36

收听Stackoverflow播客,在那里Joel和Jeff谈论了同样的问题。 Joel谈到他们提供托管软件版本的经验。他指出,将客户端ID添加到数据库中会使设计和代码变得复杂(您确定没有意外忘记将其添加到某个WHERE子句中吗?),并且会增加托管功能的复杂性,例如客户特定的备份。

这是第20或21集(请查看交录以获取详细信息)。


16
这是第19集,时间为[50:45] => https://stackoverflow.fogbugz.com/default.asp?W24218 - Vitor Silva

24
在我看来,这将取决于您潜在的客户群。 如果你能够进入一个情况,即劲敌都在使用你的系统,那么你最好选择单独的数据库。 这也取决于DBMS如何实现多个数据库。 如果每个数据库都有一个单独的基础设施副本,则表明需要单个数据库(或更改DBMS)。 如果单个基础设施副本可以为多个数据库提供服务,则我会选择单独的数据库。
考虑数据库备份。 客户A说:“请给我发送我的数据副本”。 在单独的数据库设置中比共享单个数据库要容易得多。 考虑删除客户; 同样,在单独的数据库中更容易。
(“基础架构”部分是含糊不清的,因为不同的DBMS之间关于什么构成“数据库”与“服务器实例”之间存在重大差异,例如。补充:问题被标记为“mysql”,因此这些想法可能并不完全相关)
还有一个问题 - 在单个数据库中有多个客户时,每个SQL查询都需要确保选择正确客户的数据。 这意味着SQL将更难编写和阅读,DBMS将不得不在处理数据时更加努力,索引将更大,等等。 我确实会为许多用途选择每个客户一个单独的数据库。
显然,像StackOverflow这样的网站(仅作为例子)并没有每个用户一个单独的数据库; 我们都使用同一个数据库。 但是,如果您正在运行不同公司的会计系统,我认为共享数据库将不可接受(对于公司以及可能不接受法律人员而言)。

15
  • 开发 为了快速开发,请为每个客户使用一个数据库。想象一下备份、恢复或删除客户数据有多容易。或者测量/监控/计费使用情况。您不需要编写代码来完成它,只需使用数据库基元。

  • 性能 为了提高性能,请为所有用户使用一个数据库。考虑连接池、共享内存、缓存等问题。

  • 业务 如果你的业务计划是拥有大量小客户(比如 hotmail),那么你应该在单个数据库上工作。并且将所有管理任务(例如注册、删除、数据迁移等)完全自动化,并以友好的界面公开。如果你计划拥有几十个到几百个大客户,那么你可以为每个客户使用一个数据库,并准备系统管理脚本,供你的客户支持人员操作。


11

对于多租户,通常共享资源的能力越强,性能就越好,详见http://en.wikipedia.org/wiki/Multitenancy

所以如果可以的话,请使用单个数据库。我同意,安全问题只会由于漏洞引起,因为您可以在应用程序中实现所有访问控制。在某些数据库中,您仍然可以通过谨慎使用视图来使用数据库访问控制(以便每个经过身份验证的用户获得不同的视图)。

还有提供可扩展性的方法。例如,您可以创建一个带有扩展属性的单个表(由租户、基本记录和扩展属性ID进行键入)。或者,您可以创建每个租户的扩展表,以便每个租户都有自己的扩展架构。


7
当你设计一个多租户数据库时,通常有三种选择:
  1. 每个租户使用一个数据库
  2. 每个租户使用一个模式
  3. 所有租户共享相同的表
你选择的选项会对可扩展性、可扩展性和隔离性产生影响。这些影响已经在不同的StackOverflow问题和数据库文章中广泛讨论。
实际上,这三种设计选项 - 经过足够的努力 - 可以解决关于规模、数据在租户之间变化以及隔离的问题。决策取决于您正在构建的主要维度。总结如下:
  • 如果你正在构建可扩展性:所有租户共享相同的表
  • 如果您正在构建隔离:为每个租户创建一个数据库
例如,Google和Salesforce遵循第一种模式,并共享他们的租户表。另一方面,Stackoverflow遵循第二种模式,并保留每个租户一个数据库。第二种方法在监管行业(如医疗保健)中也更为普遍。
这个决策取决于你优化数据库设计的主要维度。 这篇关于为规模设计SaaS数据库的文章讨论了权衡,并在PostgreSQL的背景下提供了摘要。

5
另一个需要考虑的问题是,您可能有法律义务将一家公司的数据与另一家公司的数据分开保存。

4
每个客户端拥有一个数据库通常不具备良好的可扩展性。MySQL(和可能是其他数据库)每个表会保持资源打开状态,这对于一个实例上的10k+表在大规模多租户情况下并不适用。当然,如果您在达到这个级别之前遇到了其他问题,这可能并不相关。
此外,“分片”多租户应用程序很可能是随着应用程序越来越大而做的正确事情。然而,分片并不意味着每个租户都有一个数据库(或实例),而是每个分片或一组分片都可以有几个租户。您需要自己发现正确的调整参数,可能需要在生产环境中进行调整(因此从一开始就需要非常可调)。
我不能保证这点。

0

您可以从单个数据库开始,随着应用程序的增长将其分区。如果这样做,我建议您注意以下几点:

1)以易于分区的方式设计数据库。例如,如果客户要共享数据,请确保该数据在每个数据库中都可以轻松复制。

2)当您只有一个数据库时,请确保它正在备份到另一台物理服务器。在故障转移的情况下,您可以将流量恢复到此其他服务器,并仍然保持数据完整。


你在第一句中说的“如果客户要共享数据”是什么意思?我面临的情况是,必须跨客户共享数据才能被管理实体访问,那你会如何设计呢? - Bram Vandenbussche

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接