65

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

我不确定数据库方面的最佳方法是什么。我应该使用单个数据库并向每个表添加特定于客户端的列,还是应该为每个新客户端创建一个数据库?一个重要的因素是自动化:我希望创建一个新客户变得非常简单(也许可以为自己注册)。

我可以考虑使用一个数据库的可能缺点:

  • 缺乏可扩展性
  • 安全问题(尽管一开始就不应该存在错误)

您对此有何看法?您对上述公司最有可能选择哪种解决方案有任何想法吗?

4

9 回答 9

37

我通常将 ClientID 添加到所有表并使用一个数据库。但由于数据库通常难以扩展,我还将为部分或所有客户端在不同的数据库实例上运行成为可能。

这样,您可以在一个数据库中拥有一堆小客户端,而在不同的服务器上拥有大客户端。

但是,可维护性的一个关键因素是您在所有数据库中保持模式相同。在不引入特定于客户端的模式的情况下管理版本控制将非常令人头疼。

于 2008-11-01T08:21:14.380 回答
36

收听 Joel 和 Jeff 谈论相同问题的 Stackoverflow 播客。Joel 正在谈论他们提供软件托管版本的经验。他指出,在您的数据库中添加客户端 ID 会使设计和代码复杂化(您确定您没有不小心忘记将其添加到某些 WHERE 子句中吗?)并使托管功能(例如特定于客户端的备份)复杂化。

它出现在第 20 集或第 21 集中(详情请查看成绩单)。

于 2008-11-01T16:19:48.640 回答
24

在我看来,这将取决于您可能的客户群。如果您可能遇到主要竞争对手都在使用您的系统的情况,那么使用单独的数据库会更好。它还取决于您的 DBMS 如何实现多个数据库。如果每个数据库都有一个单独的基础架构副本,那么这表明只有一个数据库(或 DBMS 的更改)。如果基础设施的一个副本可以为多个数据库提供服务,那么我会选择单独的数据库。

想想数据库备份。客户 A 说“请向我发送一份我的数据”。与共享单个数据库相比,在单独的数据库设置中要容易得多。考虑移除一个客户;同样,使用单独的数据库要容易得多。

(例如,“基础设施”部分是粉饰的,因为不同的 DBMS 在“数据库”和“服务器实例”的构成方面存在重大差异。 添加:问题被标记为“mysql”,所以也许这些想法是不完全相关。)

添加:还有一个问题 - 在单个数据库中有多个客户,每个 SQL 查询都需要确保选择正确客户的数据。这意味着 SQL 将更难编写和读取,DBMS 将不得不更加努力地处理数据,索引会更大,而且......我真的会使用单独的数据库客户用于多种用途。

显然,StackOverflow(例如)没有每个用户单独的数据库;我们都使用相同的数据库。但是,如果您为不同的公司运行会计系统,我认为共享数据库是不可接受的(对公司而言,可能对法律人员而言也是如此)。

于 2008-11-01T15:58:39.150 回答
15
  • 开发 为了快速开发,请为每个客户使用一个数据库。想想备份、恢复或删除客户数据是多么容易。或测量/监控/账单使用情况。您无需自己编写代码,只需使用您的数据库原语即可。

  • 性能 为了性能,请为所有人使用数据库。想想连接池、共享内存、缓存等。

  • 业务 如果您的业务计划是拥有大量小客户(想想 hotmail),您可能应该在单个数据库上工作。并让所有管理任务(如注册、删除、数据迁移等)完全自动化并显示在友好的界面中。如果您计划拥有数十个或多达数百个大客户,那么您可以在每个客户一个数据库中工作,并拥有可由您的客户支持人员操作的系统管理脚本。

于 2009-02-15T12:54:20.827 回答
11

对于多租户,性能通常会增加您设法在租户之间共享的资源越多,请参阅

http://en.wikipedia.org/wiki/Multitenancy

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

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

于 2008-11-01T08:04:28.000 回答
7

在设计多租户数据库时,通常有三个选项:

  1. 每个租户拥有一个数据库
  2. 每个租户有一个架构
  3. 让所有租户共享同一张桌子

您选择的选项会影响可伸缩性、可扩展性和隔离性。这些影响已在不同的StackOverflow 问题和数据库文章中得到广泛讨论。

在实践中,三个设计选项中的每一个——只要付出足够的努力——都可以解决有关规模、跨租户变化的数据和隔离的问题。该决定取决于您要构建的主要维度。摘要:

  • 如果您正在构建规模:让所有租户共享同一张桌子
  • 如果您正在构建隔离:为每个租户创建一个数据库

例如,Google和 Salesforce 遵循第一种模式并让他们的租户共享相同的表。另一方面,Stackoverflow 遵循第二种模式,并为每个租户保留一个数据库。第二种方法在医疗保健等受监管的行业中也更为常见。

决定归结为您优化数据库设计的主要维度。这篇关于为规模设计 SaaS 数据库的文章讨论了权衡取舍,并提供了 PostgreSQL 上下文中的摘要。

于 2016-10-08T18:38:40.680 回答
5

要考虑的另一点是,您可能有法律义务将一家公司的数据与另一家公司的数据分开。

于 2008-11-01T20:52:06.267 回答
4

每个客户端拥有一个数据库通常不能很好地扩展。MySQL(可能还有其他数据库)为每个表保留打开的资源,这不适合一个实例上的 10k+ 个表,这在大规模多租户情况下会发生。

当然,如果您在达到此级别之前有其他问题导致其他问题,这可能无关紧要。

此外,随着您的应用程序变得越来越大,“分片”多租户应用程序最终可能是正确的做法。

然而,分片并不意味着每个租户一个数据库(或实例),而是每个分片或一组分片一个,每个分片可能有多个租户。您将需要为自己找到正确的调整参数,可能在生产中(因此它可能需要从一开始就进行相当的调整)

€ 我不能保证。

于 2008-11-01T21:07:59.120 回答
0

您可以从单个数据库开始,并随着应用程序的增长对其进行分区。如果你这样做,我会推荐几件事:

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

2)当您只有一个数据库时,请确保将其备份到另一台物理服务器。如果发生故障转移,您可以将流量恢复到这台其他服务器,并且您的数据仍然完好无损。

于 2009-01-02T23:15:17.223 回答