我应该为多客户端应用程序使用单个还是多个数据库设置?
我正在开发一个旨在简化公司工作stream程和项目pipe理的PHP应用程序,让我们来说一下像Basecamp和GoPlan 。
我不确定最好的方法是数据库方式。 我应该使用单个数据库并为每个表添加客户特定的列,还是应该为每个新客户创build一个数据库? 一个重要的因素是自动化:我希望它创build一个新的客户端(也许开放自己注册的可能性)是简单的。
使用一个数据库可以考虑的可能的缺点:
- 缺乏可扩展性
- 安全问题(尽pipe错误不应该在那里 )
你对此有什么想法? 你有什么想法上述公司最有可能select什么解决scheme?
我通常将ClientID添加到所有表中并使用一个数据库。 但是由于数据库通常很难扩展,所以我也可以在一些或所有的客户端上运行不同的数据库实例。
这样,你可以在一个数据库中拥有一堆小型客户机,在不同的服务器上拥有大型的小型客户机。
尽pipe如此,可维护性的一个关键因素是您可以在所有数据库中使模式保持一致。 没有介绍客户特定的模式,将会有足够的头痛来pipe理版本。
收听Joel和Jeff谈到的同一个问题的Stackoverflow播客。 Joel正在谈论他们提供软件托pipe版本的经验。 他指出,在您的数据库中添加客户端ID会使devise和代码变得复杂(您是否确实意外忘记将其添加到某个WHERE子句中?),并使主机function复杂化,如客户端特定的备份。
这是在第20集或第21集(查看成绩单的细节)。
在我看来,这取决于你可能的客户群。 如果你可能陷入一个竞争对手都在使用你的系统的情况,那么你最好使用单独的数据库。 这也取决于你的DBMS如何实现多个数据库。 如果每个数据库都有一个独立的基础架构副本,则表明有单个数据库(或DBMS的更改)。 如果多个数据库可以由一个单一的基础架构副本服务,那么我会去单独的数据库。
考虑数据库备份。 客户A说“请给我一份我的数据”。 在单独的数据库设置中,与共享单个数据库相比,要容易得多。 想想移除一个客户; 再次,单独的数据库更容易。
(“基础结构”部分是口头的,因为不同的数据库pipe理系统关于什么构成“数据库”与“服务器实例”之间存在主要差异。Add:问题被标记为“mysql”,所以也许这些想法完全相关。)
添加 :另外一个问题 – 在单个数据库中有多个客户,每个SQL查询将需要确保select正确客户的数据。 这意味着SQL将更难以编写和读取,并且DBMS将不得不更加努力地处理数据,并且索引将会更大,并且…我真的会用一个单独的数据库顾客为了多种目的。
显然,StackOverflow(作为例子)没有一个单独的数据库每个用户; 我们都使用相同的数据库。 但是,如果您正在为不同的公司运行会计系统,我不认为这是可以接受的(对公司,而不是法人)共享数据库。
-
开发为了快速开发,请使用每个客户的数据库。 想想备份,还原或删除客户数据将会多么容易。 或者测量/监测/计费使用情况。 你不需要自己编写代码来完成它,只需要使用你的数据库原语。
-
性能对于性能,请使用全部数据库。 考虑连接池,共享内存,caching等
-
业务如果你的商业计划是有很多小客户(想想hotmail),你应该可以在一个数据库上工作。 并将所有pipe理任务如注册,删除,数据迁移等完全自动化并在友好的界面中显示。 如果您打算拥有几十个或几百个大客户,那么您可以为每个客户在一个数据库中工作,并制定可由客户支持人员操作的系统pipe理脚本。
对于多租户来说,性能通常会增加您在租户中共享的更多资源,请参阅
http://en.wikipedia.org/wiki/Multitenancy
所以,如果可以的话,去一个单一的数据库。 我同意安全问题只会由于错误而发生,因为您可以在应用程序中实现所有访问控制。 在某些数据库中,仍然可以通过仔细使用视图来使用数据库访问控制(以便每个经过身份validation的用户都可以获得不同的视图)。
还有一些方法可以提供可扩展性。 例如,您可以创build一个具有扩展属性(由租户,基logging和扩展属性ID键入)的单个表。 或者您可以创build每个租户的扩展表,这样每个租户都有自己的扩展模式。
以下屏幕截图解释了如何在salesforce.com上完成此操作。 他们使用一个数据库和一个专门的OrgId列来标识每个租户的数据。 还有更多,所以你应该看看这个。 我会用他们的方法去。
在MSDN上还有另外一篇很棒的文章 。 它深入地解释了何时应该使用共享或孤立的方法。 请记住,为所有租户拥有共享数据库有一些重要的安全隐患,如果它们都共享相同的数据库对象,您可能需要使用[行级安全性] – 具体取决于您使用的DBMS(我确信可以在MS SQL Server和Oracle,也可能在IBM DB2中)。 您可以使用像MySQL中的行级安全技巧来实现类似的结果(视图+触发器)。
还有一点需要考虑的是,您可能有责任将一家公司的数据与其他公司的数据分开。
每个客户端有一个数据库通常不能很好地扩展。 MySQL(也可能是其他数据库)占用每个表的资源,这在一个实例中并不适用于10k +表,这在大规模的多租户情况下会发生。
当然,如果在达到这个级别之前还有其他问题导致了其他问题,这可能就没有关系了。
此外,多租户应用程序的“分片”可能最终是正确的,因为您的应用程序变得越来越大。
然而,分片并不意味着每个租户有一个数据库(或实例),而是每个分片或一组分片(每个分片可能有几个租户)。 你将需要为自己发现正确的调整参数,可能在生产中(因此它可能需要从一开始就非常可调)
€我不能保证。
在devise多租户数据库时,通常有三种select:
- 每个租户有一个数据库
- 每个租户有一个模式
- 让所有租户共用同一张桌子
您select的选项会影响可伸缩性,可扩展性和隔离性。 这些影响已经在不同的StackOverflow问题和数据库文章中被广泛讨论。
在实践中,三个devisescheme中的每一个都可以通过足够的努力解决规模问题,租户之间不同的数据以及隔离问题。 这个决定取决于你正在build立的主要维度。 摘要:
- 如果你正在规模build设:让所有租户共享同一个表(S)
- 如果您正在构build隔离:为每个租户创build一个数据库
例如, Google和Salesforce遵循第一种模式,并让他们的租户共享相同的表格。 另一方面,Stackoverflow遵循第二种模式,并为每个租户保留一个数据库。 第二种方法在受监pipe的行业,例如医疗保健领域也较为普遍。
这个决定归结为你正在优化数据库devise的主要方面。 这篇关于deviseSaaS数据库规模的文章讨论了权衡,并在PostgreSQL的上下文中提供了一个总结。
您可以从一个数据库开始,并在应用程序增长时对其进行分区。 如果你这样做,我会推荐几件事情:
1)以易于分区的方式devise数据库。 例如,如果客户要共享数据,请确保数据容易在每个数据库中复制。
2)如果只有一个数据库,请确保将其备份到另一台物理服务器。 如果发生故障切换,您可以将stream量恢复到其他服务器,并保持数据不变。