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

时间:2008-11-01 07:25:32

标签: database-design architecture database-schema multi-tenant

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

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

我可以考虑使用一个数据库:

  • 缺乏可扩展性
  • 安全问题(虽然错误不应该首先出现

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

10 个答案:

答案 0 :(得分:37)

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

通过这种方式,您可以在一个数据库中拥有大量小型客户端,而在不同服务器上拥有大型客户端。

可维护性的一个关键因素是,您在所有数据库中保持架构相同。如果不引入客户端特定的模式,将会有足够的麻烦来管理版本控制。

答案 1 :(得分:34)

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

这是第20集或第21集(查看成绩单的详细信息)。

答案 2 :(得分:22)

在我看来,这取决于您可能的客户群。如果你可能遇到主要竞争对手都在使用你的系统的情况,那么你最好使用不同的数据库。它还取决于DBMS如何实现多个数据库。如果每个数据库都有一个单独的基础结构副本,则建议使用单个数据库(或更改DBMS)。如果基础架构的单个副本可以提供多个数据库,那么我将使用单独的数据库。

考虑数据库备份。客户A说“请寄给我一份我的数据”。在单独的数据库设置中,比共享单个数据库要容易得多。考虑删除客户;再次,使用单独的数据库会更容易。

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

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

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

答案 3 :(得分:13)

  • <强>发 为了快速开发,请为每个客户使用数据库。想想备份,恢复或删除客户数据是多么容易。或者衡量/监控/账单使用情况。您不需要自己编写代码,只需使用数据库原语。

  • <强>性能 为了提高性能,请为所有人使用数据库。考虑连接池,共享内存,缓存等。

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

答案 4 :(得分:12)

以下screencast解释了它是如何在salesforce.com上完成的。他们使用一个带有特殊列OrgId的数据库来识别每个租户的数据。还有更多,所以你应该看看这个。我会采用他们的方法。

在MSDN上有另一个很棒的article。当您应该使用共享或隔离方法时,它会深入解释。 请记住,为所有租户提供共享数据库会产生一些重要的安全隐患,如果他们共享相同的数据库对象,您可能需要使用[行级别安全] - 这取决于您使用的DBMS(我确信它可能在MS中使用) SQL Server和Oracle,也可能在IBM DB2中)。您可以使用row level security in mySQL之类的技巧来获得类似的结果(视图+触发器)。

答案 5 :(得分:10)

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

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

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

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

答案 6 :(得分:5)

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

  1. 每个租户有一个数据库
  2. 每个租户都有一个架构
  3. 让所有租户共享同一张表
  4. 您选择的选项会影响可伸缩性,可扩展性和隔离性。已经在不同的StackOverflow questions和数据库文章中广泛讨论了这些含义。

    在实践中,三种设计方案中的每一种 - 只需付出足够的努力 - 就可以解决有关规模的问题,不同租户的数据以及隔离问题。决定取决于您正在构建的主要维度。摘要:

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

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

    决定归结为您为数据库设计优化的主要方面。 This article on designing your SaaS database for scale讨论了权衡,并在PostgreSQL的背景下提供了摘要。

答案 7 :(得分:4)

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

答案 8 :(得分:4)

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

当然,如果您在达到此级别之前还有其他问题导致其他问题,则可能不相关。

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

然而,分片并不意味着每个租户有一个数据库(或实例),而是每个分片或一组分片,每个分片可能有几个租户。您需要为自己发现正确的调整参数,可能是在生产中(因此从一开始它可能需要非常可调)

€我无法保证。

答案 9 :(得分:0)

您可以从单个数据库开始,并在应用程序增长时对其进行分区。如果你这样做,我会推荐一些事情:

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

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